2

我有这行玩具语言的代码。-functionprint接受参数列表并打印这些参数。

print(a, (a := 5, a))

如果我使用按值调用或按名称调用,输出会有所不同吗?如果是这样,输出将是什么。

可以假设a被初始化为0

4

1 回答 1

4

使用“按值调用”的参数通常是从左到右计算的(在大多数语言中),所以表达式相当于这样:

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可以以任何顺序(和任何次数)评估它们。

于 2016-09-09T13:29:02.423 回答