3 ms·
Your stupid Lisp trick for the day: In Heresy, one of my contributors had a clever moment when he realized that Y can be generalized in Lisps to take multiple a
by jarcane 11y ago
Your stupid Lisp trick for the day: In Heresy, one of my contributors had a clever moment when he realized that Y can be generalized in Lisps to take multiple arguments, because technically Lisp lambdas always take just one argument in reality: a list of arguments. So this:
; Y
; The Y-combinator
(def Y
(fn (b)
((fn (f) (b (fn (x) ((f f) x))))
(fn (f) (b (fn (x) ((f f) x)))))))
Becomes this:
;; Y*
;; the Y-combinator, generalized for multiple argument functions
(def Y*
(fn (b)
((fn (f) (b (fn args (apply (f f) args))))
(fn (f) (b (fn args (apply (f f) args)))))))
And thus can be used with multiple argument functions. But then we can further have some fun with a simple little macro like this:
; (fnlet *name* args body ...)
; A syntax sugaring for less verbose use of Y
; Allows lambda functions that can still self-refer
; uses the generalized Y-combinator
(def macro fnlet (name args body ...)
(Y*
(fn (name)
(fn args
body ...))))
And now we have a lambda that can have it's own local name:
> (map (fnlet fib (n)
(select
((zero? n) 0)
((one? n) 1)
(else (+ (fib (- n 2)) (fib (- n 1))))))
(range 0 to 20))
'(0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765)
- tu7001 11y agoGood stuff!