0

我有一些功能:

def f(x: Int) = x * x

然后我称之为:

var y = 0
f { y += 1; y }

为上述代码生成的字节码如下所示:

     0: iconst_0      
     1: istore_1      
     2: aload_0       
     3: iload_1       
     4: iconst_1      
     5: iadd          
     6: istore_1      
     7: iload_1       
     8: invokevirtual #18                 // Method f:(I)I
    11: pop           
    12: return

如果我更改函数def f(x: Int)来表示按名称调用:

def f(x: => Int) = x * x

为同一部分代码生成的字节码如下所示:

     0: new           #24                 // class scala/runtime/IntRef
     3: dup           
     4: iconst_0      
     5: invokespecial #28                 // Method scala/runtime/IntRef."<init>":(I)V
     8: astore_1      
     9: aload_0
     ....

我的问题是:

对于 Call-by-Name,我们对引用进行操作是一个规则,还是取决于编译中的语义分析阶段?

4

1 回答 1

2

按名称形式参数的实际参数总是被打包成一个所谓的“thunk”(这个术语可以追溯到 1960 年代的 Algol),这使得有可能有​​零、一个或多个(任何数字)包含实际参数的表达式的评估。如果该表达式中存在副作用,则有关多重评估的内容很重要。

该“引用”的具体用途与将在被调用函数中执行的代码将对调用var方法中的局部变量(字面意思是 a )产生副作用有关。这就是为什么涉及。在这种情况下,将始终使用一种或另一种“引用”(取决于在实际参数表达式中引用的类型)。如果不涉及,则将该值简单地复制到 thunk。IntRefvarvar

于 2014-04-18T15:28:25.057 回答