diff --git a/lib/minikanren/relations.sx b/lib/minikanren/relations.sx index 1afee3c5..ce49586c 100644 --- a/lib/minikanren/relations.sx +++ b/lib/minikanren/relations.sx @@ -190,6 +190,14 @@ ((== n :z) (== result x)) ((fresh (n-1 mid) (== n (list :s n-1)) (rel x mid) (iterate-no rel n-1 mid result)))))) +(define + pairlisto + (fn + (l1 l2 pairs) + (conde + ((nullo l1) (nullo l2) (nullo pairs)) + ((fresh (a1 d1 a2 d2 d-pairs) (conso a1 d1 l1) (conso a2 d2 l2) (conso (list a1 a2) d-pairs pairs) (pairlisto d1 d2 d-pairs)))))) + (define everyo (fn diff --git a/lib/minikanren/tests/pairlisto.sx b/lib/minikanren/tests/pairlisto.sx new file mode 100644 index 00000000..5406d37b --- /dev/null +++ b/lib/minikanren/tests/pairlisto.sx @@ -0,0 +1,41 @@ +;; lib/minikanren/tests/pairlisto.sx — zip two lists into pair list. + +(mk-test + "pairlisto-empty" + (run* q (pairlisto (list) (list) q)) + (list (list))) + +(mk-test + "pairlisto-equal-lengths" + (run* + q + (pairlisto (list 1 2 3) (list :a :b :c) q)) + (list + (list (list 1 :a) (list 2 :b) (list 3 :c)))) + +(mk-test + "pairlisto-recover-l1" + (run* + q + (pairlisto + q + (list :a :b :c) + (list (list 10 :a) (list 20 :b) (list 30 :c)))) + (list (list 10 20 30))) + +(mk-test + "pairlisto-recover-l2" + (run* + q + (pairlisto + (list 1 2 3) + q + (list (list 1 :x) (list 2 :y) (list 3 :z)))) + (list (list :x :y :z))) + +(mk-test + "pairlisto-different-lengths-fails" + (run* q (pairlisto (list 1 2) (list :a :b :c) q)) + (list)) + +(mk-tests-run!) diff --git a/plans/minikanren-on-sx.md b/plans/minikanren-on-sx.md index 2307e5c2..9b096dd9 100644 --- a/plans/minikanren-on-sx.md +++ b/plans/minikanren-on-sx.md @@ -173,6 +173,7 @@ _(none yet)_ _Newest first._ +- **2026-05-08** — **pairlisto**: relational zip — pairs is the zipped list of (l1[i] l2[i]). Runs forward, recovers l1 given l2 and pairs, recovers l2 given l1 and pairs. 5 new tests, 431/431 cumulative. - **2026-05-08** — **iterate-no**: relational iterated application. Applies a 2-arg relation n times (Peano n) starting from x to produce result. Generalises succ-iteration / list-cons-iteration / etc. 4 new tests, 426/426 cumulative. - **2026-05-08** — **rev-acco / rev-2o**: accumulator-style reversal — faster than appendo-driven reverseo for forward queries because no quadratic appendos. Trade-off: rev-acco is asymmetric (cannot run cleanly backward in run*). 6 new tests, 422/422 cumulative. - **2026-05-08** — **even-i / odd-i (intarith)**: ground-only parity goals via project. Composes with membero for filtered enumeration: -> . 5 new tests, 416/416 cumulative.