Parameters 按需致电计划
我的代码知道参数是通过按需调用传递的: 我觉得我遗漏了什么,但在按需调用Parameters 按需致电计划,parameters,scheme,parameter-passing,anonymous-recursion,call-by-need,Parameters,Scheme,Parameter Passing,Anonymous Recursion,Call By Need,我的代码知道参数是通过按需调用传递的: 我觉得我遗漏了什么,但在按需调用foo时,该对象为f,它将计算f一次,然后将永远不会更新res和n。这是正确的吗?我错过什么了吗 谢谢。你说得对。只有通过名称调用,begin表达式才会在每次调用f时进行计算(第一次除外)——只有在确实调用了f的情况下,才能找出我们调用的是什么 通过值调用,begin表达式在第一次调用foo之前只计算一次 对于按需调用,它最多可能得到一次评估,如果在第一次调用foo结束时需要再次调用f 让我们看看如何在常规的按值调用方案中
foo
时,该对象为f
,它将计算f
一次,然后将永远不会更新res
和n
。这是正确的吗?我错过什么了吗
谢谢。你说得对。只有通过名称调用,
begin
表达式才会在每次调用f
时进行计算(第一次除外)——只有在确实调用了f
的情况下,才能找出我们调用的是什么
通过值调用,begin
表达式在第一次调用foo
之前只计算一次
对于按需调用,它最多可能得到一次评估,如果在第一次调用foo
结束时需要再次调用f
让我们看看如何在常规的按值调用方案中模拟按名称调用版本: 呼叫
(fact2 5)
在球拍中产生120
对于按值调用语义,您的代码不需要更改(将在常规的按值调用方案中进行解释),当然,对于(fact-25)
调用,您的代码将循环(实际上,在Racket中也是如此)
在“按需调用”语义下,每个lambda的主体(两个新lambda包装器的主体)将仅在第一次调用时进行评估,然后保存计算值并返回;对于所有后续调用,将立即返回保存的值,而不计算主体。因此,
设置代码>表单最多会被评估一次,并且代码,以及示例测试调用(fact-25)
将再次循环。在第一次调用foo
之后,foo
在无限循环中调用自身。由于foo
只是在调用自身,因此数值参数n
永远不会递减,因此永远不会达到零来终止循环。根据我的老师,你错了,它应该在(开始…)中不断更新n但我不明白为什么,因为在callby need中,只要添加一点输出,就可以很容易地显示出来。在foo
中添加一行,如(显示“输入foo:n:”)(显示n)(换行符)
,作为第一行。然后调用(事实2-5)
。您将看到一个无休止的输出流,其中使用参数4调用foo
。@clataq--callby need是一个懒惰的计算模型,Scheme急切地计算函数调用中的参数。您不能在Scheme REPL中运行此代码,以便在按需调用模型下对其行为进行推理。您能解释更多吗?我只看到fact-2
使用参数n
和foo
调用foo
。而foo
只调用带有参数n
和foo
的foo
。没有任何地方可以减少foo
减量n
。我没有看到任何关于懒惰的记忆或其他机制被建立起来。@clartaq具体解释什么?我的回答中有三种说法。你是在问需要打电话吗?具体来说,您的问题是什么?是的,关于“按需调用”(或任何其他参数传递约定)。如果没有可见的方法阻止foo
递归,我就看不出任何对fact-2
的调用如何能够成功。否则,我将重复O.P.s.的问题。“我遗漏了什么吗?”谢谢你的坚持。@clartaq我已经编辑了答案。:)在“按值调用”下,操作代码不需要更改,当然会循环,对于(fact-25)
调用。@adabsurdum“…将出现非终止循环。”是的,就是这样。我的意思是,我们必须做一些修改,以表示OP代码的按名称调用解释,以在Racket的按值调用系统中运行的代码来表示;所以,不需要任何更改来通过值解释来表示其调用,因为Racket已经是这样了。
(define fact-2
(let ((foo (lambda (n f)
(if (zero? n)
1
(f n f)))))
(lambda (n)
(let ((res 1))
(foo n (begin
(set! res (* res n))
(set! n (- n 1))
foo))
res))))
(define fact2
(let ((foo (lambda (n f)
(if (zero? (n)) ;; (n) NB
1
((f) n f))))) ;; (f) NB
(lambda (n)
(let ((res 1))
(foo (lambda () n) ;; (lambda () ...) NB
(lambda () ;; (lambda () ...) NB
(begin
(set! res (* res n))
(set! n (- n 1))
foo)))
res))))