;; lib/minikanren/tests/fresh.sx — Phase 2 piece B tests for `fresh`. ;; --- empty fresh: pure goal grouping --- (mk-test "fresh-empty-vars-equiv-conj" (stream-take 5 ((fresh () (== 1 1)) empty-s)) (list empty-s)) (mk-test "fresh-empty-vars-no-goals-is-succeed" (stream-take 5 ((fresh ()) empty-s)) (list empty-s)) ;; --- single var --- (mk-test "fresh-one-var-bound" (let ((s (first (stream-take 5 ((fresh (x) (== x 7)) empty-s))))) (first (vals s))) 7) ;; --- multiple vars + multiple goals --- (mk-test "fresh-two-vars-three-goals" (let ((q (mk-var "q")) (g (fresh (x y) (== x 10) (== y 20) (== q (list x y))))) (mk-walk* q (first (stream-take 5 (g empty-s))))) (list 10 20)) (mk-test "fresh-three-vars" (let ((q (mk-var "q")) (g (fresh (a b c) (== a 1) (== b 2) (== c 3) (== q (list a b c))))) (mk-walk* q (first (stream-take 5 (g empty-s))))) (list 1 2 3)) ;; --- fresh interacts with disj --- (mk-test "fresh-with-disj" (let ((q (mk-var "q"))) (let ((g (fresh (x) (mk-disj (== x 1) (== x 2)) (== q x)))) (let ((res (stream-take 5 (g empty-s)))) (map (fn (s) (mk-walk q s)) res)))) (list 1 2)) ;; --- nested fresh --- (mk-test "fresh-nested" (let ((q (mk-var "q")) (g (fresh (x) (fresh (y) (== x 1) (== y 2) (== q (list x y)))))) (mk-walk* q (first (stream-take 5 (g empty-s))))) (list 1 2)) ;; --- call-fresh (functional alternative) --- (mk-test "call-fresh-binds-and-walks" (let ((s (first (stream-take 5 ((call-fresh (fn (x) (== x 99))) empty-s))))) (first (vals s))) 99) (mk-test "call-fresh-distinct-from-outer-vars" (let ((q (mk-var "q"))) (let ((g (call-fresh (fn (x) (mk-conj (== x 5) (== q (list x x))))))) (mk-walk* q (first (stream-take 5 (g empty-s)))))) (list 5 5)) (mk-tests-run!)