Scheme rewrite let* as nested unary lets

China☆狼群 提交于 2019-12-12 05:29:01

问题


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.


回答1:


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.




回答2:


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.



来源:https://stackoverflow.com/questions/5112623/scheme-rewrite-let-as-nested-unary-lets

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!