kernel: apply combinator + 7 tests [shapes-reflective]
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 32s

(apply F (list V1 V2 V3)) ≡ (F V1 V2 V3). Unwrap applicative first to
skip auto-eval (args are values), then kernel-combine with the
underlying operative. Universal pattern in reflective Lisps —
sketched into the combiner.sx API. 296 tests total.
This commit is contained in:
2026-05-11 21:17:24 +00:00
parent 78dab5b28c
commit 6d8f11e093
3 changed files with 44 additions and 0 deletions

View File

@@ -559,6 +559,28 @@
(kernel-combine fn-val (list acc (first xs)) dyn-env)
dyn-env)))))
;; (apply COMBINER ARGS-LIST) — call COMBINER with the elements of
;; ARGS-LIST as arguments. The Kernel canonical use: turn a constructed
;; list of values into a function call. We skip the applicative's
;; auto-eval step (via unwrap) because ARGS-LIST is already values, not
;; expressions; for a bare operative, we pass through directly.
(define kernel-apply-applicative
(kernel-make-primitive-applicative-with-env
(fn (args dyn-env)
(cond
((not (= (length args) 2))
(error "apply: expects (combiner args-list)"))
((not (kernel-combiner? (first args)))
(error "apply: first arg must be a combiner"))
((not (list? (nth args 1)))
(error "apply: second arg must be a list"))
(:else
(let ((op (cond
((kernel-applicative? (first args))
(kernel-unwrap (first args)))
(:else (first args)))))
(kernel-combine op (nth args 1) dyn-env)))))))
(define kernel-reduce-applicative
(kernel-make-primitive-applicative-with-env
(fn (args dyn-env)
@@ -794,6 +816,7 @@
(kernel-env-bind! env "map" kernel-map-applicative)
(kernel-env-bind! env "filter" kernel-filter-applicative)
(kernel-env-bind! env "reduce" kernel-reduce-applicative)
(kernel-env-bind! env "apply" kernel-apply-applicative)
(kernel-env-bind! env "not" kernel-not-applicative)
(kernel-env-bind! env "make-encapsulation-type"
kernel-make-encap-type-applicative)

View File

@@ -395,4 +395,24 @@
(ks-eval "(reduce ($lambda (acc x) (cons x acc)) () (list 1 2 3))")
(list 3 2 1))
;; ── apply ────────────────────────────────────────────────────────
(ks-test "apply: + over list"
(ks-eval "(apply + (list 1 2 3 4 5))") 15)
(ks-test "apply: lambda"
(ks-eval "(apply ($lambda (a b c) (* a (+ b c))) (list 2 3 4))") 14)
(ks-test "apply: list identity"
(ks-eval "(apply list (list 1 2 3))") (list 1 2 3))
(ks-test "apply: empty args list"
(ks-eval "(apply + (list))") 0)
(ks-test "apply: single arg list"
(ks-eval "(apply ($lambda (x) (* x 10)) (list 7))") 70)
(ks-test "apply: built via map+apply"
;; (apply + (map ($lambda (x) (* x x)) (list 1 2 3))) → 1+4+9 = 14
(ks-eval
"(apply + (map ($lambda (x) (* x x)) (list 1 2 3)))") 14)
(ks-test "apply: error on non-list args"
(guard (e (true :raised))
(ks-eval "(apply + 5)"))
:raised)
(define ks-tests-run! (fn () {:total (+ ks-test-pass ks-test-fail) :passed ks-test-pass :failed ks-test-fail :fails ks-test-fails}))