Pregunta

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.

¿Fue útil?

Solución

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.

Otros consejos

Here is a definition of let* in syntax-rules-like pseudocode that you can use to write your own version:

(let* ((a b) (c d) ...) body ...) === (let ((a b)) (let* ((c d) ...) body ...))
(let* () body ...) === body

You should be able to turn that into a function using match or a macro using syntax-rules.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top