diff --git a/lib/minikanren/relations.sx b/lib/minikanren/relations.sx index 84d4e76b..60200c86 100644 --- a/lib/minikanren/relations.sx +++ b/lib/minikanren/relations.sx @@ -156,3 +156,19 @@ (conde ((fresh (a d) (conso a d l) (rel a))) ((fresh (a d) (conso a d l) (someo rel d)))))) + +(define + lasto + (fn + (l x) + (conde + ((conso x (list) l)) + ((fresh (a d) (conso a d l) (lasto d x)))))) + +(define + init-o + (fn + (l init) + (conde + ((fresh (x) (conso x (list) l) (== init (list)))) + ((fresh (a d d-init) (conso a d l) (conso a d-init init) (init-o d d-init)))))) diff --git a/lib/minikanren/tests/lasto.sx b/lib/minikanren/tests/lasto.sx new file mode 100644 index 00000000..110f8019 --- /dev/null +++ b/lib/minikanren/tests/lasto.sx @@ -0,0 +1,38 @@ +;; lib/minikanren/tests/lasto.sx — last-element + init-without-last. + +(mk-test + "lasto-singleton" + (run* q (lasto (list 5) q)) + (list 5)) +(mk-test + "lasto-multi" + (run* q (lasto (list 1 2 3 4) q)) + (list 4)) +(mk-test "lasto-empty" (run* q (lasto (list) q)) (list)) + +(mk-test "lasto-strings" (run* q (lasto (list "a" "b" "c") q)) (list "c")) + +(mk-test + "init-o-multi" + (run* q (init-o (list 1 2 3 4) q)) + (list (list 1 2 3))) + +(mk-test + "init-o-singleton" + (run* q (init-o (list 7) q)) + (list (list))) + +(mk-test "init-o-empty" (run* q (init-o (list) q)) (list)) + +(mk-test + "lasto-init-o-roundtrip" + (run* + q + (fresh + (init last) + (lasto (list 1 2 3 4) last) + (init-o (list 1 2 3 4) init) + (appendo init (list last) q))) + (list (list 1 2 3 4))) + +(mk-tests-run!) diff --git a/plans/minikanren-on-sx.md b/plans/minikanren-on-sx.md index fd39efa1..3515133f 100644 --- a/plans/minikanren-on-sx.md +++ b/plans/minikanren-on-sx.md @@ -173,6 +173,10 @@ _(none yet)_ _Newest first._ +- **2026-05-08** — **lasto / init-o**: classic head/tail-style list relations. + lasto extracts the final element; init-o extracts everything-but-the-last. + Together with appendo, the round-trip `init ⊕ (last) = l` holds. 8 new + tests, 344/344 cumulative. - **2026-05-08** — **Datalog-style relational database queries**: tests/rdb.sx shows miniKanren as a query engine over fact tables. Defines two tables (employees + project assignments), wraps each with a relation that does