据我所知,以下是let,let*,letrec和letrec*是在方案/球拍中使用的合成糖。
现在,如果我有一个简单的程序:
(let ((x 1)
(y 2))
(+ x y))它被翻译成:
((lambda (x y) (+ x y)) 1 2)如果我有:
(let* ((x 1)
(y 2))
(+ x y))它被翻译成:
((lambda (x) ((lambda (y) (+ x y))) 2) 1)现在,对于我的第一个问题,我理解了letrec表达式的含义,它使人能够在let中使用递归,但我不知道它到底是如何实现的。letrec被翻译成什么?
例如,什么将
(letrec ((x 1)
(y 2))
(+ x y)) 被翻译成?
第二个问题与letrec*类似--但对于letrec*,我不明白它与letrec到底有什么不同?另外,letrec*表达式将被转换成什么?
发布于 2018-05-31 23:55:35
参见Oscar Waddell,Dipanwita Sarkar和R.Kent Dybvig的论文"Fixing Letrec: A Faithful Efficient Implementation of Scheme‘s Recursive Binding Construct“。
本文从一个简单的版本开始,接着解释了一个更复杂的扩展:
发布于 2018-06-02 06:10:06
由于您的示例没有任何过程,也没有实际的表达式,我认为您可以将其实现为:
(let ((x 1) (y 2))
(+ x y)) 但是为了支持表单的意图,一个基本的实现可能会这样做:
(let ((x 'undefined) (y 'undefined))
(let ((tmpx 1) (tmpy 2))
(set! x tmpx)
(set! y tmpy))
(+ x y))现在。letrec是为了让lambda能够用名字来称呼自己。所以想象一下:
(let ((fib (lambda (n)
(if (< n 2) n
(+ (fib (- n 1)) (fib (- n 2)))))))
(fib 10))重要的是要理解这是不起作用的以及为什么。将其转换为lambda调用可以很容易地看到:
((lambda (fib)
(fib 10))
(lambda (n)
(if (< n 2) n
(+ (fib (- n 1)) (fib (- n 2))))))在创建fib之后,您需要以某种方式评估lambda。假设我们这样做:
(let ((fib 'undefined))
(set! fib (lambda (n)
(if (< n 2) n
(+ (fib (- n 1)) (fib (- n 2))))))
(fib 10))或者,您也可以使用Z combinator来使其成为纯对象:
(let ((fib (Z (lambda (fib)
(lambda (n)
(if (< n 2) n
(+ (fib (- n 1)) (fib (- n 2)))))))))
(fib 10))这需要通过实现做更多的工作,但至少你没有改变。要让它与几个相互递归绑定一起工作,可能需要做更多的工作,但我相信这是可行的。
这是正确做到这一点的唯一两种方法。我知道clojure有一个模仿递归的recur,但实际上是一个goto。
对于不从letrec绑定生成闭包的变量,它们的工作方式是let,后来更像是let*,因为Soegaards对修复的回答是向后兼容的,有些人已经对其进行了调整。但是,如果您编写了兼容的代码,就不应该这样认为。
https://stackoverflow.com/questions/50627845
复制相似问题