我已经查看了所有关于letrec的信息,但我仍然不明白它作为一种特性给语言带来了什么。似乎所有用letrec表示的东西都可以像递归函数一样容易编写。但是,如果letrec已经支持递归函数,那么是否有理由公开letrec作为编程语言的特性?为什么有几种语言同时公开这两种语言?
我知道letrec可能用于实现其他特性,包括递归函数,但这与为什么它本身应该是一个特性无关。我还读到,有些人发现在某些lisps中,递归函数比递归函数更易读,但这同样与此无关,因为语言的设计人员可以努力使递归函数具有足够的可读性,从而不需要其他特性。最后,有人告诉我,letrec可以更简洁地表示某些递归值,但我还没有找到一个有动机的例子。
发布于 2017-12-10 16:36:04
define是letrec。这使我们能够首先编写递归定义。
考虑一下
let fact = fun (n => (n==0 -> 1 ; n * fact (n-1)))这个定义的正文中的名称fact指的是哪个实体?在let foo = val中,val是以已知的实体定义的,因此不能引用尚未定义的foo。就范围而言,这可以说(而且通常是),let方程的RHS定义在外部范围内。
内部fact真正指向被定义的对象的唯一方法是使用letrec,其中被定义的实体可以引用定义它的范围。因此,虽然在实体的定义正在进行时导致对其进行评估是一个错误,但是在使用letrec的情况下,存储对其(此时的未来)值的引用是可以的。
您所指的define只是另一个名称下的letrec。在计划中也是。
如果没有定义实体引用自身的能力,即在具有非递归let的语言中,就必须使用诸如Y-组合器这样的神秘设备来进行递归。这很麻烦,而且通常效率很低。另一种方法是定义如下
let fact = (fun (f => f f)) (fun (r => n => (n==0 -> 1 ; n * r r (n-1))))因此,letrec给表带来了实现的效率,也给程序员带来了方便。
那么,为什么公开非递归的let呢?哈斯克尔确实没有。该方案既有letrec,也有let。一个原因可能是为了完整性。另一个可能是更简单的let实现,内存中的自引用运行时结构减少,使垃圾收集器更容易使用。
你想要一个激励的例子。考虑将Fibonacci数定义为一个自引用的惰性列表:
letrec fibs = {0} + {1} + add fibs (tail fibs) 使用非递归let,将定义列表fibs的另一个副本,用作元素级加法函数add的输入。这将导致用术语定义fibs的另一个副本。以此类推;访问n_th Fibonacci数将导致在运行时创建和维护_n-1列表链!不是一张漂亮的照片。
这是假设同样的fibs也被用于tail fibs。如果没有,所有的赌注都取消了。
需要的是fibs使用它自己,引用它自己,所以只维护一个列表副本。
发布于 2017-12-10 17:40:47
注意:虽然这不是一个方案的具体问题,但我正在使用Scheme来演示这些差异。希望你能读懂一些lisp代码
letrec只是一个特殊的let,在定义绑定本身之前,表示它们的值的表达式才会被计算出来。想象一下:
(define (fib n)
(let ((fib (lambda (n a b)
(if (zero? n)
a
(fib (- n 1) b (+ a b))))))
(fib n))此代码失败,因为虽然fib确实存在于let的主体中,但它确实存在于闭包中,因为当计算lambda时,绑定不存在。要修复这个letrec,我们来拯救一下:
(define (fib n)
(letrec ((fib (lambda (n a b)
(if (zero? n)
a
(fib (- n 1) b (+ a b))))))
(fib n))letrec只是执行如下操作的语法:
(define (fib n)
(let ((fib 'undefined))
(let ((tmp (lambda (n a b)
(if (zero? n)
a
(fib (- n 1) b (+ a b))))))
(set! fib tmp))
(fib n)))因此,在这里可以清楚地看到,当计算lambda时,当绑定被设置为闭包本身时,fib就会存在。绑定是相同的,只是它的指针已经改变了。这是循环参考101。
那么,当你创建一个全局函数时会发生什么呢?显然,如果要递归,则需要在对lambda进行评估或环境发生突变之前存在。这里也需要解决同样的问题。
在功能语言实现中,变异是不确定的,您可以使用Y(或Z)组合器来解决这个问题。
如果您对语言的实现方式感兴趣,我建议您从马特·米尔斯文章开始。
https://stackoverflow.com/questions/47739579
复制相似问题