Set predicates: foldl/4, list_to_set/2, intersection/3, subtract/3, union/3
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled

Adds 5 new built-in predicates to the Prolog runtime with 15 tests.
390 → 405 tests across 20 suites (all passing).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-25 12:22:03 +00:00
parent 73080bb7de
commit 5a83f4ef51
5 changed files with 325 additions and 6 deletions

View File

@@ -1169,6 +1169,50 @@
false))))))))
(else false)))))
(define
pl-solve-foldl!
(fn
(db goal lst vin vout trail k)
(let
((l (pl-walk-deep lst)) (v0 (pl-walk vin)))
(cond
((and (pl-atom? l) (= (pl-atom-name l) "[]"))
(if (pl-unify! vout v0 trail) (k) false))
((and (pl-compound? l) (= (pl-fun l) "."))
(let
((head (first (pl-args l))) (tail (nth (pl-args l) 1)))
(let
((v1-var (pl-mk-rt-var "_FV")))
(let
((call-goal (pl-apply-goal goal (list head v0 v1-var))))
(if
(pl-solve-once! db call-goal trail)
(pl-solve-foldl! db goal tail v1-var vout trail k)
false)))))
(else false)))))
(define
pl-list-to-set-sx
(fn
(lst seen)
(if
(empty? lst)
(list)
(let
((head (first lst)) (tail (rest lst)))
(if
(some (fn (s) (pl-struct-eq? head s)) seen)
(pl-list-to-set-sx tail seen)
(cons head (pl-list-to-set-sx tail (cons head seen))))))))
(define
pl-pl-list-contains?
(fn
(pl-lst elem)
(let
((sx-lst (pl-prolog-list-to-sx (pl-walk-deep pl-lst))))
(some (fn (x) (pl-struct-eq? elem x)) sx-lst))))
(define
pl-solve!
(fn
@@ -1758,6 +1802,84 @@
((cond-g (pl-walk (first (pl-args g))))
(action-g (pl-walk (nth (pl-args g) 1))))
(pl-solve-forall! db cond-g action-g trail cut-box k)))
((and (pl-compound? g) (= (pl-fun g) "foldl") (= (len (pl-args g)) 4))
(pl-solve-foldl!
db
(pl-walk (first (pl-args g)))
(pl-walk (nth (pl-args g) 1))
(pl-walk (nth (pl-args g) 2))
(pl-walk (nth (pl-args g) 3))
trail
k))
((and (pl-compound? g) (= (pl-fun g) "list_to_set") (= (len (pl-args g)) 2))
(let
((lst-rt (pl-walk (first (pl-args g))))
(res-rt (pl-walk (nth (pl-args g) 1))))
(if
(pl-proper-list? lst-rt)
(let
((sx-lst (map (fn (x) (pl-walk-deep x)) (pl-prolog-list-to-sx lst-rt))))
(let
((unique-lst (pl-list-to-set-sx sx-lst (list))))
(pl-solve-eq! res-rt (pl-list-to-prolog unique-lst) trail k)))
false)))
((and (pl-compound? g) (= (pl-fun g) "intersection") (= (len (pl-args g)) 3))
(let
((s1-rt (pl-walk (first (pl-args g))))
(s2-rt (pl-walk (nth (pl-args g) 1)))
(res-rt (pl-walk (nth (pl-args g) 2))))
(if
(and (pl-proper-list? s1-rt) (pl-proper-list? s2-rt))
(let
((s1-sx (map (fn (x) (pl-walk-deep x)) (pl-prolog-list-to-sx s1-rt)))
(s2-sx
(map
(fn (x) (pl-walk-deep x))
(pl-prolog-list-to-sx s2-rt))))
(let
((inter (filter (fn (x) (some (fn (y) (pl-struct-eq? x y)) s2-sx)) s1-sx)))
(pl-solve-eq! res-rt (pl-list-to-prolog inter) trail k)))
false)))
((and (pl-compound? g) (= (pl-fun g) "subtract") (= (len (pl-args g)) 3))
(let
((s1-rt (pl-walk (first (pl-args g))))
(s2-rt (pl-walk (nth (pl-args g) 1)))
(res-rt (pl-walk (nth (pl-args g) 2))))
(if
(and (pl-proper-list? s1-rt) (pl-proper-list? s2-rt))
(let
((s1-sx (map (fn (x) (pl-walk-deep x)) (pl-prolog-list-to-sx s1-rt)))
(s2-sx
(map
(fn (x) (pl-walk-deep x))
(pl-prolog-list-to-sx s2-rt))))
(let
((diff (filter (fn (x) (not (some (fn (y) (pl-struct-eq? x y)) s2-sx))) s1-sx)))
(pl-solve-eq! res-rt (pl-list-to-prolog diff) trail k)))
false)))
((and (pl-compound? g) (= (pl-fun g) "union") (= (len (pl-args g)) 3))
(let
((s1-rt (pl-walk (first (pl-args g))))
(s2-rt (pl-walk (nth (pl-args g) 1)))
(res-rt (pl-walk (nth (pl-args g) 2))))
(if
(and (pl-proper-list? s1-rt) (pl-proper-list? s2-rt))
(let
((s1-sx (map (fn (x) (pl-walk-deep x)) (pl-prolog-list-to-sx s1-rt)))
(s2-sx
(map
(fn (x) (pl-walk-deep x))
(pl-prolog-list-to-sx s2-rt))))
(let
((s2-only (filter (fn (x) (not (some (fn (y) (pl-struct-eq? x y)) s1-sx))) s2-sx)))
(let
((union-lst (append s1-sx s2-only)))
(pl-solve-eq!
res-rt
(pl-list-to-prolog union-lst)
trail
k))))
false)))
(true (pl-solve-user! db g trail cut-box k))))))
(define