scalac for Call-by-Name使用引用

时间:2014-04-18 13:54:00

标签: scala bytecode scalac

我有一些功能:

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,我们是否会对引用进行操作或依赖于编译中的语义分析阶段?

1 个答案:

答案 0 :(得分:2)

按名称形式参数的实际参数总是被打包成一个所谓的“thunk”(术语在20世纪60年代一直回到Algol),这使得有可能存在零,一个或多个(对包含实际参数的表达式的任何数量的评估。如果该表达式中存在副作用,那么关于多次评估的这一点很重要。

该“引用”的具体用法与这样一个事实有关,即在被调用函数中执行的代码将对<的一个局部变量(字面意思,特别是var)产生副作用。 em>调用方法。这就是IntRef涉及的原因。在这种情况下,将始终使用某种或那种“ref”(取决于在实际参数表达式中引用的var的类型)。如果不涉及var,则只将值复制到thunk。