我有这行玩具语言的代码。-functionprint
接受参数列表并打印这些参数。
print(a, (a := 5, a))
如果我使用按值调用或按名称调用,输出会有所不同吗?如果是这样,输出将是什么。
可以假设a
被初始化为0
。
我有这行玩具语言的代码。-functionprint
接受参数列表并打印这些参数。
print(a, (a := 5, a))
如果我使用按值调用或按名称调用,输出会有所不同吗?如果是这样,输出将是什么。
可以假设a
被初始化为0
。
使用“按值调用”的参数通常是从左到右计算的(在大多数语言中),所以表达式相当于这样:
arg1 := a // copy value of a to arg1
a := 5 // copy 5 to a
arg2 := a // copy value of a to arg2
print(arg1, arg2) // print(0, 5)
“按名称调用”显然是一种惰性求值形式,它会产生如下结果:
arg1 := function() {return a;}
arg2 := function() {a := 5; return a;}
print(arg1, arg2)
所以在这种情况下,结果将取决于两件事:
a := 5
则不会影响a
第一个闭包捕获的值。然而,大多数允许重新分配局部变量的语言都实现了按引用捕获(例如 JavaScript)。print
- 取决于它的编写方式。如果闭包按值捕获,print(…)
则将产生0 5
,因为赋值a := 5
仅影响第二个闭包的a
.
如果闭包通过引用捕获,那么我只能猜测输出可能是什么。但该函数很可能print
会执行以下操作:
print := function(lazy x, lazy y) {
writeToOutput(x())
writeToOutput(y())
}
在这种情况下,结果将是相同的 ( 0 5
),因为x()
首先评估,处理结果,然后y()
评估。在这种情况下,a
直到函数完成后,值才会改变x
。
但这只是一个猜测;print
可以以任何顺序(和任何次数)评估它们。