Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 捕获变量的嵌套函数是否分配_Scala_Closures_Nested Function - Fatal编程技术网

Scala 捕获变量的嵌套函数是否分配

Scala 捕获变量的嵌套函数是否分配,scala,closures,nested-function,Scala,Closures,Nested Function,scala中的嵌套函数可以捕获父函数中的变量 e、 g def外部={ 变量a=0 def内部={ a=42 } 内部的 A. } 在C中,这是通过将所有捕获的变量存储在一个结构上,并在byref中传递该结构来实现的。这避免了嵌套函数的分配,除非将其转换为函数对象。在夏普实验室见 但是,在scala中,您不能通过ref传递变量,因此唯一可行的方法是将所有捕获的变量存储在一个对象上,然后将该对象传入 这是否意味着,如果嵌套函数捕获scala中的任何变量,它的每次调用都将进行分配?变量a本身仍然位于

scala中的嵌套函数可以捕获父函数中的变量

e、 g

def外部={ 变量a=0 def内部={ a=42 } 内部的 A. } 在C中,这是通过将所有捕获的变量存储在一个结构上,并在byref中传递该结构来实现的。这避免了嵌套函数的分配,除非将其转换为函数对象。在夏普实验室见

但是,在scala中,您不能通过ref传递变量,因此唯一可行的方法是将所有捕获的变量存储在一个对象上,然后将该对象传入

这是否意味着,如果嵌套函数捕获scala中的任何变量,它的每次调用都将进行分配?

变量a本身仍然位于外部方法的堆栈框架中,而它引用的对象在堆上进行分配,因为即使假定a代表基元类型,所有Java对象也是如此

通过在您的代码上运行javap-v,我们可以看到a实际上是scala.runtime.IntRef类型的最终变量,它包含一个可以更新的整数字段。嵌套的内部方法被转换为一个静态方法,该方法接受一个IntRef类型的参数,并将其elem字段设置为42。这有点类似于C方法,但是为每个变量创建一个对象,而不是一个结构来保存所有变量

public int outer();                                                                                          
descriptor: ()I                                                                                                         
flags: (0x0001) ACC_PUBLIC                                                                                              
Code:                                                                                                                     
stack=1, locals=2, args_size=1                                                                                             
0: iconst_0                                                                                                             
1: invokestatic  #16                 // Method scala/runtime/IntRef.create:
(I)Lscala/runtime/IntRef;                    
4: astore_1                                                                                                             
5: aload_1                                                                                                              
6: invokestatic  #20                 // Method inner$1:(Lscala/runtime/IntRef;)V                                        
9: aload_1                                                                                                             
10: getfield      #24                 // Field scala/runtime/IntRef.elem:I                                              
13: ireturn 
编辑:这次让我们用字符串试试:

class ClosureTest {
    def outer = {
        var a = ""
        def inner() = {
            a = "42"
        }
        inner()
        a
    }
}
javap的输出:

这一次,由于String不是一个原语,所以使用了ObjectRef类,它有一个表示包装值的类型参数,但基本上还是一样的。尽管JVM不允许像C一样使用ref参数,但对象仍然是通过引用传递的,因此a保留的对象/原语的值仍然可以修改

这是我能找到的唯一文档的一个例子。还有很多其他类,比如BooleanRef、FloatRef,还有它们的volatile对应类,比如VolatileDoubleRef、VolatileObjectRef,等等。这些类中的每个类基本上只有一个可变公共字段,编译器在需要捕获变量的实际值时使用该字段。

变量a本身仍在外部方法的堆栈框架中,而它引用的对象在堆上分配,因为所有Java对象都是,甚至当一个被认为代表一个基本类型时

通过在您的代码上运行javap-v,我们可以看到a实际上是scala.runtime.IntRef类型的最终变量,它包含一个可以更新的整数字段。嵌套的内部方法被转换为一个静态方法,该方法接受一个IntRef类型的参数,并将其elem字段设置为42。这有点类似于C方法,但是为每个变量创建一个对象,而不是一个结构来保存所有变量

public int outer();                                                                                          
descriptor: ()I                                                                                                         
flags: (0x0001) ACC_PUBLIC                                                                                              
Code:                                                                                                                     
stack=1, locals=2, args_size=1                                                                                             
0: iconst_0                                                                                                             
1: invokestatic  #16                 // Method scala/runtime/IntRef.create:
(I)Lscala/runtime/IntRef;                    
4: astore_1                                                                                                             
5: aload_1                                                                                                              
6: invokestatic  #20                 // Method inner$1:(Lscala/runtime/IntRef;)V                                        
9: aload_1                                                                                                             
10: getfield      #24                 // Field scala/runtime/IntRef.elem:I                                              
13: ireturn 
编辑:这次让我们用字符串试试:

class ClosureTest {
    def outer = {
        var a = ""
        def inner() = {
            a = "42"
        }
        inner()
        a
    }
}
javap的输出:

这一次,由于String不是一个原语,所以使用了ObjectRef类,它有一个表示包装值的类型参数,但基本上还是一样的。尽管JVM不允许像C一样使用ref参数,但对象仍然是通过引用传递的,因此a保留的对象/原语的值仍然可以修改


这是我能找到的唯一文档的一个例子。还有很多其他类,比如BooleanRef、FloatRef,还有它们的volatile对应类,比如VolatileDoubleRef、VolatileObjectRef,每个类基本上只有一个可变公共字段,编译器在需要捕获变量的实际值时使用该字段。

在创建嵌套函数时捕获变量,而不是在调用嵌套函数时。在创建嵌套函数时捕获变量,而不是在调用嵌套函数时捕获变量。