parameters - 计划中的按需调用
问题描述
我有这段代码知道参数是通过需要使用调用传递的:
(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))))
我觉得我错过了一些东西,但是在需要调用foo
这个对象 as的调用中f
,它会计算f
一次,然后永远不会更新res
and n
。这个对吗?我错过了什么吗?
谢谢你。
解决方案
你是对的。只有通过名称调用,begin
表达式才会在每次调用时被评估f
(除了第一次)——以找出我们正在调用的内容,只有当调用f
确实被调用时。
使用按值调用,begin
表达式将只被评估一次,在第一次调用之前foo
。
通过按需调用,它最多可能会被评估一次,何时以及是否在第一次调用结束时foo
需要f
再次调用。
让我们看看如何在常规的按值调用方案中模拟按名称调用的版本:
(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))))
在 Racket 中调用(fact2 5)
产生。120
对于按值调用的语义,您的代码不需要更改(在常规的按值调用方案中解释)并且当然会为(fact-2 5)
调用循环(确实如此,在 Racket 中)。
并且在按需调用语义下,每个 lambda 的主体(两个新的 lambda 包装器)将仅在第一次调用时进行评估,然后它将保存计算的值然后返回它;并且对于所有后续调用,保存的值将立即返回,而不评估正文。因此,set!
表单最多将被评估一次,并且带有示例测试调用的代码 (fact-2 5)
将再次循环。
推荐阅读
- delphi - Is there a way to get just the ANSI characters from a string? Utf8decode fails when string contains emojis
- go - 有没有办法在本地机器上拥有所需的模块而不是让它们联机
- powershell - Powershell Copy-Item -recurse 不拾取新目录
- amazon-web-services - 如何使用跳转主机在 jenkins 上配置 ssh 服务器?
- javascript - VUE JS - 我的一些方法在没有我调用的情况下被调用
- css - 在 React 中更改不允许的拖动光标
- c# - 如何在 WPF 中通过 XAML 岛使用 Windows 10 样式资源
- string - 将 > 作为变量,因此它可以是 < 或 > 在 Case 是
- python - Torchvision 中的转换不起作用
- python - 使用python从另一个文件中提取文本