datalog: findall aggregate (159/159)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 53s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 53s
(findall L V Goal) — bind L to the distinct V values for which Goal holds, or the empty list when none. One-line addition to dl-do-aggregate that returns the unreduced list. Tests cover EDB, derived relation, and empty cases. Useful for "give me all the X such that ..." queries without scalar reduction.
This commit is contained in:
@@ -19,7 +19,7 @@
|
||||
;;
|
||||
;; Empty input: count → 0, sum → 0, min/max → no binding (rule fails).
|
||||
|
||||
(define dl-aggregate-rels (list "count" "sum" "min" "max"))
|
||||
(define dl-aggregate-rels (list "count" "sum" "min" "max" "findall"))
|
||||
|
||||
(define
|
||||
dl-aggregate?
|
||||
@@ -43,6 +43,7 @@
|
||||
(cond
|
||||
((= op "count") (len vals))
|
||||
((= op "sum") (dl-sum-vals vals 0))
|
||||
((= op "findall") vals)
|
||||
((= op "min")
|
||||
(cond
|
||||
((= (len vals) 0) :empty)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"lang": "datalog",
|
||||
"total_passed": 156,
|
||||
"total_passed": 159,
|
||||
"total_failed": 0,
|
||||
"total": 156,
|
||||
"total": 159,
|
||||
"suites": [
|
||||
{"name":"tokenize","passed":26,"failed":0,"total":26},
|
||||
{"name":"parse","passed":18,"failed":0,"total":18},
|
||||
@@ -11,9 +11,9 @@
|
||||
{"name":"builtins","passed":19,"failed":0,"total":19},
|
||||
{"name":"semi_naive","passed":8,"failed":0,"total":8},
|
||||
{"name":"negation","passed":10,"failed":0,"total":10},
|
||||
{"name":"aggregates","passed":10,"failed":0,"total":10},
|
||||
{"name":"aggregates","passed":13,"failed":0,"total":13},
|
||||
{"name":"api","passed":9,"failed":0,"total":9},
|
||||
{"name":"demo","passed":10,"failed":0,"total":10}
|
||||
],
|
||||
"generated": "2026-05-08T08:57:57+00:00"
|
||||
"generated": "2026-05-08T09:02:31+00:00"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# datalog scoreboard
|
||||
|
||||
**156 / 156 passing** (0 failure(s)).
|
||||
**159 / 159 passing** (0 failure(s)).
|
||||
|
||||
| Suite | Passed | Total | Status |
|
||||
|-------|--------|-------|--------|
|
||||
@@ -11,6 +11,6 @@
|
||||
| builtins | 19 | 19 | ok |
|
||||
| semi_naive | 8 | 8 | ok |
|
||||
| negation | 10 | 10 | ok |
|
||||
| aggregates | 10 | 10 | ok |
|
||||
| aggregates | 13 | 13 | ok |
|
||||
| api | 9 | 9 | ok |
|
||||
| demo | 10 | 10 | ok |
|
||||
|
||||
@@ -199,6 +199,33 @@
|
||||
(list (quote popular) (quote P)))
|
||||
(list {:P (quote p1)}))
|
||||
|
||||
;; findall: collect distinct values into a list.
|
||||
(dl-at-test-set! "findall over EDB"
|
||||
(dl-query
|
||||
(dl-program
|
||||
"p(a). p(b). p(c).
|
||||
all_p(L) :- findall(L, X, p(X)).")
|
||||
(list (quote all_p) (quote L)))
|
||||
(list {:L (list (quote a) (quote b) (quote c))}))
|
||||
|
||||
(dl-at-test-set! "findall over derived"
|
||||
(dl-query
|
||||
(dl-program
|
||||
"parent(a, b). parent(b, c). parent(c, d).
|
||||
ancestor(X, Y) :- parent(X, Y).
|
||||
ancestor(X, Z) :- parent(X, Y), ancestor(Y, Z).
|
||||
desc(L) :- findall(L, X, ancestor(a, X)).")
|
||||
(list (quote desc) (quote L)))
|
||||
(list {:L (list (quote b) (quote c) (quote d))}))
|
||||
|
||||
(dl-at-test-set! "findall empty"
|
||||
(dl-query
|
||||
(dl-program
|
||||
"p(1).
|
||||
all_q(L) :- findall(L, X, q(X)).")
|
||||
(list (quote all_q) (quote L)))
|
||||
(list {:L (list)}))
|
||||
|
||||
;; Aggregate vs single distinct.
|
||||
(dl-at-test-set! "distinct counted once"
|
||||
(dl-query
|
||||
|
||||
@@ -186,9 +186,10 @@ large graphs.
|
||||
|
||||
### Phase 8 — aggregation (Datalog+)
|
||||
- [x] `(count R V Goal)`, `(sum R V Goal)`, `(min R V Goal)`,
|
||||
`(max R V Goal)` — first arg is the result variable, second is the
|
||||
aggregated variable, third is the goal literal. Live in
|
||||
`lib/datalog/aggregates.sx`.
|
||||
`(max R V Goal)`, `(findall L V Goal)` — first arg is the result
|
||||
variable, second is the aggregated variable, third is the goal
|
||||
literal. `findall` returns the distinct-value list itself; the
|
||||
others reduce. Live in `lib/datalog/aggregates.sx`.
|
||||
- [x] `dl-eval-aggregate`: runs `dl-find-bindings` on the goal under the
|
||||
current subst (which provides outer-context bindings), collects
|
||||
distinct values of the aggregated var, applies the aggregate.
|
||||
@@ -269,6 +270,13 @@ large graphs.
|
||||
|
||||
_Newest first._
|
||||
|
||||
- 2026-05-08 — Phase 8 extension: `findall L V Goal` aggregate. Bind
|
||||
L to the list of distinct V values for which Goal holds (or the
|
||||
empty list when no matches). Implemented as a one-line case in
|
||||
`dl-do-aggregate`. 3 new tests: EDB, derived relation, empty.
|
||||
Useful for "give me all the X such that …" queries without
|
||||
scalar reduction.
|
||||
|
||||
- 2026-05-08 — Phase 5d semantic fix: anonymous `_` variables are
|
||||
renamed per occurrence at `dl-add-rule!` and `dl-query` time so
|
||||
`(p X _) (p _ Y)` no longer unifies the two `_`s. New helpers
|
||||
|
||||
Reference in New Issue
Block a user