erlang: lists flatmap/2 + filtermap/2 + mapfoldl/3 + search/2 (862/862)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 51s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 51s
Higher-order list ops in lib/erlang/lists-ext.sx. filtermap honours
true/false/{true,V}; mapfoldl returns {Mapped, Acc}; search returns
{value,E}|false. lists_ext suite 83 -> 91.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -484,6 +484,80 @@
|
||||
er-bif-lists-droplast
|
||||
(fn (vs) (er-ext-droplast (er-bif-arg1 vs "lists:droplast"))))
|
||||
|
||||
;; ── more higher-order (flatmap / filtermap / mapfoldl / search) ───
|
||||
(define
|
||||
er-ext-flatmap
|
||||
(fn (f lst)
|
||||
(cond
|
||||
(er-nil? lst) (er-mk-nil)
|
||||
(er-cons? lst)
|
||||
(er-list-append
|
||||
(er-apply-fun f (list (get lst :head)))
|
||||
(er-ext-flatmap f (get lst :tail)))
|
||||
:else (raise (er-mk-error-marker (er-mk-atom "badarg"))))))
|
||||
|
||||
(define
|
||||
er-bif-lists-flatmap
|
||||
(fn (vs) (er-ext-flatmap (nth vs 0) (nth vs 1))))
|
||||
|
||||
(define
|
||||
er-ext-atom-true?
|
||||
(fn (v) (and (er-atom? v) (= (get v :name) "true"))))
|
||||
|
||||
(define
|
||||
er-ext-filtermap
|
||||
(fn (f lst)
|
||||
(cond
|
||||
(er-nil? lst) (er-mk-nil)
|
||||
(er-cons? lst)
|
||||
(let ((r (er-apply-fun f (list (get lst :head)))))
|
||||
(cond
|
||||
(er-ext-atom-true? r)
|
||||
(er-mk-cons (get lst :head) (er-ext-filtermap f (get lst :tail)))
|
||||
(and
|
||||
(er-tuple? r)
|
||||
(= (len (get r :elements)) 2)
|
||||
(er-ext-atom-true? (nth (get r :elements) 0)))
|
||||
(er-mk-cons (nth (get r :elements) 1) (er-ext-filtermap f (get lst :tail)))
|
||||
:else (er-ext-filtermap f (get lst :tail))))
|
||||
:else (raise (er-mk-error-marker (er-mk-atom "badarg"))))))
|
||||
|
||||
(define
|
||||
er-bif-lists-filtermap
|
||||
(fn (vs) (er-ext-filtermap (nth vs 0) (nth vs 1))))
|
||||
|
||||
(define
|
||||
er-ext-mapfoldl
|
||||
(fn (f acc lst mapped)
|
||||
(cond
|
||||
(er-nil? lst)
|
||||
(er-mk-tuple (list (er-list-reverse-iter mapped (er-mk-nil)) acc))
|
||||
(er-cons? lst)
|
||||
(let ((r (er-apply-fun f (list (get lst :head) acc))))
|
||||
(let ((es (get r :elements)))
|
||||
(er-ext-mapfoldl f (nth es 1) (get lst :tail)
|
||||
(er-mk-cons (nth es 0) mapped))))
|
||||
:else (raise (er-mk-error-marker (er-mk-atom "badarg"))))))
|
||||
|
||||
(define
|
||||
er-bif-lists-mapfoldl
|
||||
(fn (vs) (er-ext-mapfoldl (nth vs 0) (nth vs 1) (nth vs 2) (er-mk-nil))))
|
||||
|
||||
(define
|
||||
er-ext-search
|
||||
(fn (pred lst)
|
||||
(cond
|
||||
(er-nil? lst) (er-mk-atom "false")
|
||||
(er-cons? lst)
|
||||
(if (er-truthy? (er-apply-fun pred (list (get lst :head))))
|
||||
(er-mk-tuple (list (er-mk-atom "value") (get lst :head)))
|
||||
(er-ext-search pred (get lst :tail)))
|
||||
:else (er-mk-atom "false"))))
|
||||
|
||||
(define
|
||||
er-bif-lists-search
|
||||
(fn (vs) (er-ext-search (nth vs 0) (nth vs 1))))
|
||||
|
||||
;; ── register ──────────────────────────────────────────────────────
|
||||
;; Hook into er-register-builtin-bifs! rather than registering once:
|
||||
;; the registry can be reset + rebuilt mid-run (tests/runtime.sx does
|
||||
@@ -516,7 +590,11 @@
|
||||
(er-register-pure-bif! "lists" "sublist" 3 er-bif-lists-sublist)
|
||||
(er-register-pure-bif! "lists" "nthtail" 2 er-bif-lists-nthtail)
|
||||
(er-register-pure-bif! "lists" "split" 2 er-bif-lists-split)
|
||||
(er-register-pure-bif! "lists" "droplast" 1 er-bif-lists-droplast)))
|
||||
(er-register-pure-bif! "lists" "droplast" 1 er-bif-lists-droplast)
|
||||
(er-register-pure-bif! "lists" "flatmap" 2 er-bif-lists-flatmap)
|
||||
(er-register-pure-bif! "lists" "filtermap" 2 er-bif-lists-filtermap)
|
||||
(er-register-pure-bif! "lists" "mapfoldl" 3 er-bif-lists-mapfoldl)
|
||||
(er-register-pure-bif! "lists" "search" 2 er-bif-lists-search)))
|
||||
|
||||
(define er-ext-prev-register-builtins er-register-builtin-bifs!)
|
||||
(define er-register-builtin-bifs!
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"language": "erlang",
|
||||
"total_pass": 854,
|
||||
"total": 854,
|
||||
"total_pass": 862,
|
||||
"total": 862,
|
||||
"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":83,"total":83,"status":"ok"}
|
||||
{"name":"lists_ext","pass":91,"total":91,"status":"ok"}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Erlang-on-SX Scoreboard
|
||||
|
||||
**Total: 854 / 854 tests passing**
|
||||
**Total: 862 / 862 tests passing**
|
||||
|
||||
| | Suite | Pass | Total |
|
||||
|---|---|---|---|
|
||||
@@ -16,7 +16,7 @@
|
||||
| ✅ | ffi | 37 | 37 |
|
||||
| ✅ | vm | 78 | 78 |
|
||||
| ✅ | send_after | 10 | 10 |
|
||||
| ✅ | lists_ext | 83 | 83 |
|
||||
| ✅ | lists_ext | 91 | 91 |
|
||||
|
||||
|
||||
Generated by `lib/erlang/conformance.sh`.
|
||||
|
||||
@@ -310,3 +310,34 @@
|
||||
|
||||
(er-lx-test "droplast single"
|
||||
(er-lx-nm "lists:droplast([9]) =:= []") "true")
|
||||
|
||||
;; ── lists:flatmap/2 ───────────────────────────────────────────────
|
||||
(er-lx-test "flatmap duplicates"
|
||||
(er-lx-nm "lists:flatmap(fun(X) -> [X,X] end, [1,2]) =:= [1,1,2,2]") "true")
|
||||
|
||||
(er-lx-test "flatmap empty"
|
||||
(er-lx-nm "lists:flatmap(fun(X) -> [X] end, []) =:= []") "true")
|
||||
|
||||
;; ── lists:filtermap/2 ─────────────────────────────────────────────
|
||||
(er-lx-test "filtermap transform"
|
||||
(er-lx-nm
|
||||
"lists:filtermap(fun(X) -> case X rem 2 of 0 -> {true, X*10}; _ -> false end end, [1,2,3,4]) =:= [20,40]")
|
||||
"true")
|
||||
|
||||
(er-lx-test "filtermap bool keep"
|
||||
(er-lx-nm "lists:filtermap(fun(X) -> X > 2 end, [1,2,3,4]) =:= [3,4]") "true")
|
||||
|
||||
;; ── lists:mapfoldl/3 ──────────────────────────────────────────────
|
||||
(er-lx-test "mapfoldl map+acc"
|
||||
(er-lx-nm
|
||||
"lists:mapfoldl(fun(X,A) -> {X*2, A+X} end, 0, [1,2,3]) =:= {[2,4,6],6}") "true")
|
||||
|
||||
(er-lx-test "mapfoldl empty"
|
||||
(er-lx-nm "lists:mapfoldl(fun(X,A) -> {X,A} end, 5, []) =:= {[],5}") "true")
|
||||
|
||||
;; ── lists:search/2 ────────────────────────────────────────────────
|
||||
(er-lx-test "search hit"
|
||||
(er-lx-nm "lists:search(fun(X) -> X > 2 end, [1,2,3,4]) =:= {value,3}") "true")
|
||||
|
||||
(er-lx-test "search miss"
|
||||
(er-lx-nm "lists:search(fun(X) -> X > 9 end, [1,2,3])") "false")
|
||||
|
||||
Reference in New Issue
Block a user