erlang: lists foldr/3 + partition/2 + takewhile/dropwhile/splitwith (823/823)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 1m5s

Higher-order traversal family in lib/erlang/lists-ext.sx, registered
pure via the er-register-builtin-bifs! wrapper. foldr right-folds;
partition returns {Yes,No} order-preserved; splitwith = {takewhile,
dropwhile}. lists_ext suite 38 -> 52.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-30 13:34:44 +00:00
parent 343c508939
commit 42a16f7cf3
5 changed files with 134 additions and 6 deletions

View File

@@ -249,6 +249,76 @@
(er-bool
(not (er-ext-lt? (er-ext-tup-elem b n) (er-ext-tup-elem a n))))))))))
;; ── higher-order traversal (foldr / partition / *while) ───────────
(define
er-ext-foldr
(fn (f acc lst)
(cond
(er-nil? lst) acc
(er-cons? lst)
(er-apply-fun f (list (get lst :head) (er-ext-foldr f acc (get lst :tail))))
:else (raise (er-mk-error-marker (er-mk-atom "badarg"))))))
(define
er-bif-lists-foldr
(fn (vs) (er-ext-foldr (nth vs 0) (nth vs 1) (nth vs 2))))
(define
er-ext-partition
(fn (pred lst yes no)
(cond
(er-nil? lst)
(er-mk-tuple
(list
(er-list-reverse-iter yes (er-mk-nil))
(er-list-reverse-iter no (er-mk-nil))))
(er-cons? lst)
(if (er-truthy? (er-apply-fun pred (list (get lst :head))))
(er-ext-partition pred (get lst :tail) (er-mk-cons (get lst :head) yes) no)
(er-ext-partition pred (get lst :tail) yes (er-mk-cons (get lst :head) no)))
:else (raise (er-mk-error-marker (er-mk-atom "badarg"))))))
(define
er-bif-lists-partition
(fn (vs) (er-ext-partition (nth vs 0) (nth vs 1) (er-mk-nil) (er-mk-nil))))
(define
er-ext-takewhile
(fn (pred lst)
(cond
(er-nil? lst) (er-mk-nil)
(er-cons? lst)
(if (er-truthy? (er-apply-fun pred (list (get lst :head))))
(er-mk-cons (get lst :head) (er-ext-takewhile pred (get lst :tail)))
(er-mk-nil))
:else (er-mk-nil))))
(define
er-bif-lists-takewhile
(fn (vs) (er-ext-takewhile (nth vs 0) (nth vs 1))))
(define
er-ext-dropwhile
(fn (pred lst)
(cond
(er-nil? lst) (er-mk-nil)
(er-cons? lst)
(if (er-truthy? (er-apply-fun pred (list (get lst :head))))
(er-ext-dropwhile pred (get lst :tail))
lst)
:else lst)))
(define
er-bif-lists-dropwhile
(fn (vs) (er-ext-dropwhile (nth vs 0) (nth vs 1))))
(define
er-bif-lists-splitwith
(fn (vs)
(let ((pred (nth vs 0)) (lst (nth vs 1)))
(er-mk-tuple
(list (er-ext-takewhile pred lst) (er-ext-dropwhile pred lst))))))
;; ── register ──────────────────────────────────────────────────────
;; Hook into er-register-builtin-bifs! rather than registering once:
;; the registry can be reset + rebuilt mid-run (tests/runtime.sx does
@@ -265,7 +335,12 @@
(er-register-pure-bif! "lists" "keyreplace" 4 er-bif-lists-keyreplace)
(er-register-pure-bif! "lists" "keystore" 4 er-bif-lists-keystore)
(er-register-pure-bif! "lists" "keytake" 3 er-bif-lists-keytake)
(er-register-pure-bif! "lists" "keysort" 2 er-bif-lists-keysort)))
(er-register-pure-bif! "lists" "keysort" 2 er-bif-lists-keysort)
(er-register-pure-bif! "lists" "foldr" 3 er-bif-lists-foldr)
(er-register-pure-bif! "lists" "partition" 2 er-bif-lists-partition)
(er-register-pure-bif! "lists" "takewhile" 2 er-bif-lists-takewhile)
(er-register-pure-bif! "lists" "dropwhile" 2 er-bif-lists-dropwhile)
(er-register-pure-bif! "lists" "splitwith" 2 er-bif-lists-splitwith)))
(define er-ext-prev-register-builtins er-register-builtin-bifs!)
(define er-register-builtin-bifs!

View File

@@ -1,7 +1,7 @@
{
"language": "erlang",
"total_pass": 809,
"total": 809,
"total_pass": 823,
"total": 823,
"suites": [
{"name":"tokenize","pass":62,"total":62,"status":"ok"},
{"name":"parse","pass":52,"total":52,"status":"ok"},
@@ -15,6 +15,6 @@
{"name":"ffi","pass":37,"total":37,"status":"ok"},
{"name":"vm","pass":78,"total":78,"status":"ok"},
{"name":"send_after","pass":10,"total":10,"status":"ok"},
{"name":"lists_ext","pass":38,"total":38,"status":"ok"}
{"name":"lists_ext","pass":52,"total":52,"status":"ok"}
]
}

View File

@@ -1,6 +1,6 @@
# Erlang-on-SX Scoreboard
**Total: 809 / 809 tests passing**
**Total: 823 / 823 tests passing**
| | Suite | Pass | Total |
|---|---|---|---|
@@ -16,7 +16,7 @@
| ✅ | ffi | 37 | 37 |
| ✅ | vm | 78 | 78 |
| ✅ | send_after | 10 | 10 |
| ✅ | lists_ext | 38 | 38 |
| ✅ | lists_ext | 52 | 52 |
Generated by `lib/erlang/conformance.sh`.

View File

@@ -154,3 +154,54 @@
(er-lx-test "keysort stable on equal keys"
(er-lx-nm
"lists:keysort(1, [{a,1},{a,2},{a,3}]) =:= [{a,1},{a,2},{a,3}]") "true")
;; ── lists:foldr/3 ─────────────────────────────────────────────────
(er-lx-test "foldr preserves order"
(er-lx-nm
"lists:foldr(fun(X,Acc) -> [X|Acc] end, [], [1,2,3]) =:= [1,2,3]") "true")
(er-lx-test "foldr sum"
(erlang-eval-ast "lists:foldr(fun(X,A) -> X+A end, 0, [1,2,3,4])") 10)
(er-lx-test "foldr empty returns acc"
(erlang-eval-ast "lists:foldr(fun(X,A) -> X+A end, 42, [])") 42)
;; ── lists:partition/2 ─────────────────────────────────────────────
(er-lx-test "partition evens/odds"
(er-lx-nm
"lists:partition(fun(X) -> X rem 2 =:= 0 end, [1,2,3,4,5]) =:= {[2,4],[1,3,5]}")
"true")
(er-lx-test "partition all satisfy"
(er-lx-nm "lists:partition(fun(_) -> true end, [1,2]) =:= {[1,2],[]}") "true")
(er-lx-test "partition empty"
(er-lx-nm "lists:partition(fun(_) -> true end, []) =:= {[],[]}") "true")
;; ── lists:takewhile/2 ─────────────────────────────────────────────
(er-lx-test "takewhile prefix"
(er-lx-nm "lists:takewhile(fun(X) -> X < 3 end, [1,2,3,4,1]) =:= [1,2]") "true")
(er-lx-test "takewhile none"
(er-lx-nm "lists:takewhile(fun(X) -> X < 0 end, [1,2]) =:= []") "true")
(er-lx-test "takewhile all"
(er-lx-nm "lists:takewhile(fun(X) -> X < 9 end, [1,2,3]) =:= [1,2,3]") "true")
;; ── lists:dropwhile/2 ─────────────────────────────────────────────
(er-lx-test "dropwhile prefix"
(er-lx-nm "lists:dropwhile(fun(X) -> X < 3 end, [1,2,3,4,1]) =:= [3,4,1]") "true")
(er-lx-test "dropwhile all"
(er-lx-nm "lists:dropwhile(fun(X) -> X < 9 end, [1,2,3]) =:= []") "true")
(er-lx-test "dropwhile none"
(er-lx-nm "lists:dropwhile(fun(X) -> X < 0 end, [1,2]) =:= [1,2]") "true")
;; ── lists:splitwith/2 ─────────────────────────────────────────────
(er-lx-test "splitwith"
(er-lx-nm
"lists:splitwith(fun(X) -> X < 3 end, [1,2,3,4,1]) =:= {[1,2],[3,4,1]}") "true")
(er-lx-test "splitwith empty"
(er-lx-nm "lists:splitwith(fun(_) -> true end, []) =:= {[],[]}") "true")