;; lib/minikanren/fresh.sx — Phase 2 piece B: `fresh` for introducing ;; logic variables inside a goal body. ;; ;; (fresh (x y z) goal1 goal2 ...) ;; ≡ (let ((x (make-var)) (y (make-var)) (z (make-var))) ;; (mk-conj goal1 goal2 ...)) ;; ;; A macro rather than a function so user-named vars are real lexical ;; bindings — which is also what miniKanren convention expects. ;; The empty-vars form (fresh () goal ...) is just a goal grouping. (defmacro fresh (vars &rest goals) (quasiquote (let (unquote (map (fn (v) (list v (list (quote make-var)))) vars)) (mk-conj (splice-unquote goals))))) ;; call-fresh — functional alternative for code that builds goals ;; programmatically: ;; ((call-fresh (fn (x) (== x 7))) empty-s) → ({:_.N 7}) (define call-fresh (fn (f) (fn (s) ((f (make-var)) s))))