;; lib/minikanren/conda.sx — Phase 5 piece A: `conda`, the soft-cut. ;; ;; (conda (g0 g ...) (h0 h ...) ...) ;; — first clause whose head g0 produces ANY answer wins; ALL of g0's ;; answers are then conj'd with the rest of that clause; later ;; clauses are NOT tried. ;; — differs from condu only in not wrapping g0 in onceo: condu ;; commits to the SINGLE first answer, conda lets the head's full ;; answer-set flow into the rest of the clause. ;; (Reasoned Schemer chapter 10; Byrd 5.3.) (define conda-try (fn (clauses s) (cond ((empty? clauses) mzero) (:else (let ((cl (first clauses))) (let ((head-goal (first cl)) (rest-goals (rest cl))) (let ((peek (stream-take 1 (head-goal s)))) (if (empty? peek) (conda-try (rest clauses) s) (mk-bind (head-goal s) (mk-conj-list rest-goals)))))))))) (defmacro conda (&rest clauses) (quasiquote (fn (s) (conda-try (list (splice-unquote (map (fn (cl) (quasiquote (list (splice-unquote cl)))) clauses))) s))))