diff --git a/lib/minikanren/relations.sx b/lib/minikanren/relations.sx index 758d1df1..35d87cb5 100644 --- a/lib/minikanren/relations.sx +++ b/lib/minikanren/relations.sx @@ -277,6 +277,14 @@ ((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 + zip-with-o + (fn + (rel l1 l2 result) + (conde + ((nullo l1) (nullo l2) (nullo result)) + ((fresh (a1 d1 a2 d2 a-result d-result) (conso a1 d1 l1) (conso a2 d2 l2) (rel a1 a2 a-result) (conso a-result d-result result) (zip-with-o rel d1 d2 d-result)))))) + (define swap-firsto (fn diff --git a/lib/minikanren/tests/zip-with-o.sx b/lib/minikanren/tests/zip-with-o.sx new file mode 100644 index 00000000..c3cea9ab --- /dev/null +++ b/lib/minikanren/tests/zip-with-o.sx @@ -0,0 +1,52 @@ +;; lib/minikanren/tests/zip-with-o.sx — element-wise combine of two lists. + +(mk-test + "zip-with-o-empty" + (run* q (zip-with-o pluso-i (list) (list) q)) + (list (list))) + +(mk-test + "zip-with-o-pluso-i" + (run* + q + (zip-with-o + pluso-i + (list 1 2 3) + (list 10 20 30) + q)) + (list (list 11 22 33))) + +(mk-test + "zip-with-o-times-i" + (run* + q + (zip-with-o + *o-i + (list 2 3 4) + (list 5 6 7) + q)) + (list (list 10 18 28))) + +(mk-test + "zip-with-o-different-length-fails" + (run* + q + (zip-with-o + pluso-i + (list 1 2) + (list 1 2 3) + q)) + (list)) + +(mk-test + "zip-with-o-non-arith-rel" + (run* + q + (zip-with-o + (fn (a b r) (== r (list a b))) + (list :x :y) + (list 1 2) + q)) + (list (list (list :x 1) (list :y 2)))) + +(mk-tests-run!)