Reputation: 315
I am trying to use Dog Hoyte's Let over Lambda, Chapter 3, named let with some touch from EmacsLisp (named-let from subr-x.el).
Neither his original, nor mine slightly modified version macroexpand in SBCL. I am not sure I understand what is wrong there, can someone give me a pointer please?
(defmacro nlet (name bindings &rest body)
"Looping construct taken from Scheme.
Like `let', bind variables in BINDINGS and then evaluate BODY,
but with the twist that BODY can evaluate itself recursively by
calling NAME, where the arguments passed to NAME are used
as the new values of the bound variables in the recursive invocation.
Implementation after D. Hoyte from \"Let over lambda\"."
(let ((fargs (mapcar (lambda (b) (if (consp b) (car b) b)) bindings))
(aargs (mapcar (lambda (b) (if (consp b) (cadr b))) bindings)))
`(labels ((,name ,fargs ,@body))
(,name ,aargs))))
When trying to macroexpand-all, it bangs with error.
Expected expansion:
(macroexpand-all
'(nlet fact ((n n))
(if (zerop n)
1
(* n (fact (- n 1))))))
=> (labels ((fact (n) (if (zerop n) 1 (* n (fact (- n 1)))))) (fact (n)))
What I get:
Illegal function call in method body:
((N N))
[Condition of type SIMPLE-ERROR]
Restarts:
0: [RETRY] Retry SLY mREPL evaluation request.
1: [ABORT] Return to sly-db level 1.
2: [RETRY] Retry SLY mREPL evaluation request.
3: [*ABORT] Return to SLY's top level.
4: [ABORT] abort thread (#<THREAD tid=15104 "sly-channel-1-mrepl-remote-1" RUNNING {1100BC0003}>)
Backtrace:
0: (SB-WALKER::GET-WALKER-TEMPLATE (N N) ((N N)))
1: ((LAMBDA NIL :IN SB-WALKER::WALK-FORM-INTERNAL))
SBCL code walker does not like my template. Why? :) Seems like it tries to execute the bindings to the label-expression during the macro expansion for some reason?
Upvotes: 0
Views: 62