compiler-construction - 在按名称调用和按值调用下会打印什么?

标签 compiler-construction functional-programming sml callbyname call-by-value

我有这行玩具语言代码。 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)

“call-by-name”显然是一种惰性求值形式,会产生如下结果:

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() 被评估。在这种情况下,直到使用 x 完成函数之后,a 的值才会更改。

但这只是一个猜测; print 可以按任何顺序(以及任意次数)对它们进行评估。

关于compiler-construction - 在按名称调用和按值调用下会打印什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39411960/

相关文章:

compiler-construction - 如何创建 JVM 编程语言?

functional-programming - 函数式编程 : Are maps sequential? 对闭包的影响

Javascript:回调中的无点样式

haskell - lambda 绑定(bind)中的模式匹配?

macos - 使用自制软件在 macOS 上安装 smlnj 不起作用

c++ - 编译/链接过程如何工作?

compiler-construction - 为什么Dart中有特殊的 “sealed”类,我该怎么做?

parsing - "expression"的非左递归 PEG 语法

c# - 多个线程调用同一函数不起作用

SML : how to compare (< or >) two equality types