As an exercise I am trying to rewrite strings representing source code for let*
as nested unary lets. Here is my best effort:
(define let*→nested-unary-lets
(match-lambda
(`(let* (()) ,<exprs>)
`(let () ,<exprs>))
(`(let* ((,<var> ,<val>)) ,<exprs>)
`(let ((,<var> ,<val>)) (let () ,<exprs>)))
(`(let* ((,<var> ,<val>) ,<clauses>) ,<exprs>)
`(let ((,<var> ,<val>)) (let*→nested-unary-lets '(let* (,@<clauses>) ,<exprs>))))))
The problem I am experiencing at the moment is that the pattern:
`(let* ((,<var> ,<val>) ,<clauses>) ,<exprs>)
does not match a string like:
'(let* ((a b) (c d) (e f)) <expressions>)
The term clauses matches only the second clause (c d)
. It seems to me that it should take all of the remaining (var val)
clauses as a list ((c d) (e f))
. At any rate I need it to do so.
Any advice is appreciated.
What baffles me is that exprs will match a list of expressions so I can't think of any reason why clauses wouldn't also do so.
You will need . ,<clauses>
since you want to match the rest of the list, not just a single element. The ,<exprs>
part will need to be . ,<exprs>
for the same reason. I believe there is other syntax specifically for matching lists, but using .
is simple and matches how lists are implemented internally.