Add call-fn dispatch for HO forms: handle both Lambda and native callable

HO forms (map, filter, reduce, etc.) now use call-fn which dispatches
Lambda → call-lambda, native callable → apply, else → clear EvalError.
Previously call-lambda crashed with AttributeError on native functions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-05 22:45:01 +00:00
parent d076fc1465
commit ef04beba00
3 changed files with 48 additions and 14 deletions

View File

@@ -632,18 +632,26 @@
;; 7. Higher-order forms
;; --------------------------------------------------------------------------
;; call-fn: unified caller for HO forms — handles both Lambda and native callable
(define call-fn
(fn (f args env)
(cond
(lambda? f) (trampoline (call-lambda f args env))
(callable? f) (apply f args)
:else (error (str "Not callable in HO form: " (inspect f))))))
(define ho-map
(fn (args env)
(let ((f (trampoline (eval-expr (first args) env)))
(coll (trampoline (eval-expr (nth args 1) env))))
(map (fn (item) (trampoline (call-lambda f (list item) env))) coll))))
(map (fn (item) (call-fn f (list item) env)) coll))))
(define ho-map-indexed
(fn (args env)
(let ((f (trampoline (eval-expr (first args) env)))
(coll (trampoline (eval-expr (nth args 1) env))))
(map-indexed
(fn (i item) (trampoline (call-lambda f (list i item) env)))
(fn (i item) (call-fn f (list i item) env))
coll))))
(define ho-filter
@@ -651,7 +659,7 @@
(let ((f (trampoline (eval-expr (first args) env)))
(coll (trampoline (eval-expr (nth args 1) env))))
(filter
(fn (item) (trampoline (call-lambda f (list item) env)))
(fn (item) (call-fn f (list item) env))
coll))))
(define ho-reduce
@@ -660,7 +668,7 @@
(init (trampoline (eval-expr (nth args 1) env)))
(coll (trampoline (eval-expr (nth args 2) env))))
(reduce
(fn (acc item) (trampoline (call-lambda f (list acc item) env)))
(fn (acc item) (call-fn f (list acc item) env))
init
coll))))
@@ -669,7 +677,7 @@
(let ((f (trampoline (eval-expr (first args) env)))
(coll (trampoline (eval-expr (nth args 1) env))))
(some
(fn (item) (trampoline (call-lambda f (list item) env)))
(fn (item) (call-fn f (list item) env))
coll))))
(define ho-every
@@ -677,7 +685,7 @@
(let ((f (trampoline (eval-expr (first args) env)))
(coll (trampoline (eval-expr (nth args 1) env))))
(every?
(fn (item) (trampoline (call-lambda f (list item) env)))
(fn (item) (call-fn f (list item) env))
coll))))
@@ -686,7 +694,7 @@
(let ((f (trampoline (eval-expr (first args) env)))
(coll (trampoline (eval-expr (nth args 1) env))))
(for-each
(fn (item) (trampoline (call-lambda f (list item) env)))
(fn (item) (call-fn f (list item) env))
coll))))