I have written a function match-rewriter
that is essentially match-lambda
except that it returns its argument if no match is found:
(define-syntax match-rewriter
(syntax-rules ()
((_ (patt body) ...)
(λ (x) (match x (patt body) ... (_ x))))))
Now I would like to use match-rewriter
to take strings representing source code for let*
and rewrite it as nested unary lets
:
(define let*→nested-unary-lets
(match-rewriter (`(let*((,<var> ,<val>) ...) ,<expr1> ,<expr2> ...)
I am really stumped over how to pattern match this. I need to return:
`(let((,<var1> ,<val1>)) let((,<var2> ,<val2>)) let((...)) ... )...) ,<expr1> . ,@<expr2>)
But the nesting has me stumped. Any advice is appreciated.
Okay, here is my best attempt:
(define let*→nested-unary-lets
(match-rewriter
(`(let* (()) ,<expr1> ,<expr2> ...)
(`(let () ,<expr1> . ,<expr2>)))
(`(let* ((,<var1> ,<val1>) (,<var2> ,<val2>) ...) ,<expr1> ,<expr2> ...)
`(let ((,<var1> ,<val1>) (let*→nested-unary-lets
'(let* ((,<var2> ,<val2>) ...) ,<expr1> . ,<expr2>)))))
))
But this is how it behaves:
(let*→nested-unary-lets '(let* ((a 1) (b (+ a 1)) (c (+ a b))) (displayln c))) '(let ((a 1) (let*→nested-unary-lets '(let* (((b c) ((+ a 1) (+ a b))) ...) (displayln c)))))
I am confused about the order of the arguments in:
(let* (((b c) ((+ a 1) (+ a b)))
It seems to me it should be:
(let* ((b (+ a 1)) (c (+ a b)))
Also, it would be nice if the call to let*→nested-unary-lets
would execute instead of just printing as text.
Yes, you can do this; it shouldn't be too difficult. Specifically, the key idea you need here is not to try to handle the whole list at once. Instead, your patterns should separate the first binding from the rest, and then wrap one let around a recursive call to let*->nested-unary-lets.
Let me know if you have trouble formulating this.