diff --git a/lib/ocaml/runtime.sx b/lib/ocaml/runtime.sx index 0c9b3e0e..0ea5c882 100644 --- a/lib/ocaml/runtime.sx +++ b/lib/ocaml/runtime.sx @@ -198,6 +198,35 @@ match ys with | [] -> failwith \"List.map2: unequal\" | hy :: ty -> f hx hy :: map2 f tx ty + + let rec take n xs = + if n <= 0 then [] + else + match xs with + | [] -> [] + | h :: t -> h :: take (n - 1) t + + let rec drop n xs = + if n <= 0 then xs + else + match xs with + | [] -> [] + | _ :: t -> drop (n - 1) t + + let rec filter_map f xs = + match xs with + | [] -> [] + | h :: t -> + match f h with + | None -> filter_map f t + | Some v -> v :: filter_map f t + + let rec flat_map f xs = + match xs with + | [] -> [] + | h :: t -> append (f h) (flat_map f t) + + let concat_map = flat_map end ;; module Option = struct diff --git a/lib/ocaml/test.sh b/lib/ocaml/test.sh index b730db9a..4c39a5ae 100755 --- a/lib/ocaml/test.sh +++ b/lib/ocaml/test.sh @@ -976,6 +976,20 @@ cat > "$TMPFILE" << 'EPOCHS' (epoch 2804) (eval "(ocaml-run \"match Blue with | (Red | Green) -> 1 | Blue -> 2\")") +;; ── More List utilities (take/drop/filter_map/flat_map) ────── +(epoch 2900) +(eval "(ocaml-run \"List.take 3 [1;2;3;4;5]\")") +(epoch 2901) +(eval "(ocaml-run \"List.drop 2 [1;2;3;4;5]\")") +(epoch 2902) +(eval "(ocaml-run \"List.filter_map (fun x -> if x > 2 then Some (x * 10) else None) [1;2;3;4]\")") +(epoch 2903) +(eval "(ocaml-run \"List.flat_map (fun x -> [x; x]) [1;2;3]\")") +(epoch 2904) +(eval "(ocaml-run \"List.take 0 [1;2;3]\")") +(epoch 2905) +(eval "(ocaml-run \"List.take 100 [1;2;3]\")") + EPOCHS OUTPUT=$(timeout 180 "$SX_SERVER" < "$TMPFILE" 2>/dev/null) @@ -1544,6 +1558,14 @@ check 2802 "(1|2|3) match 5" '0' check 2803 "(Red|Green) Red" '1' check 2804 "(Red|Green) Blue" '2' +# ── List.take/drop/filter_map/flat_map ───────────────────────── +check 2900 "List.take 3" '(1 2 3)' +check 2901 "List.drop 2" '(3 4 5)' +check 2902 "List.filter_map" '(30 40)' +check 2903 "List.flat_map double" '(1 1 2 2 3 3)' +check 2904 "List.take 0" '()' +check 2905 "List.take overflow" '(1 2 3)' + TOTAL=$((PASS + FAIL)) if [ $FAIL -eq 0 ]; then echo "ok $PASS/$TOTAL OCaml-on-SX tests passed" diff --git a/plans/ocaml-on-sx.md b/plans/ocaml-on-sx.md index 2cbb90cb..2d6d0a26 100644 --- a/plans/ocaml-on-sx.md +++ b/plans/ocaml-on-sx.md @@ -377,6 +377,9 @@ the "mother tongue" closure: OCaml → SX → OCaml. This means: _Newest first._ +- 2026-05-08 Phase 6 — `List.take/drop/filter_map/flat_map/concat_map` + (+6 tests, 400 total). Common functional helpers, all written in + OCaml. **400-test milestone.** - 2026-05-08 Phase 1+3 — or-patterns `(P1 | P2 | ...)` parens-only (+5 tests, 394 total). Parser: when `|` follows a pattern inside parens, build `(:por ALT1 ALT2 ...)`. Eval: try alternatives, succeed