Julia函数参数引用

时间:2016-02-06 00:05:56

标签: reference pass-by-reference julia

文档说

  

在Julia中,函数的所有参数都通过引用传递。

所以我很惊讶地发现这两个函数的行为存在差异:

function foo!(r::Array{Int64})                                                                                                                                                                                     
        r=r+1                                                                                                                                                                                                      
end


function foobar!(r::Array{Int64})                                                                                                                                                                                  
        for i=1:length(r)                                                                                                                                                                                          
                r[i]=r[i]+1                                                                                                                                                                                        
        end                                                                                                                                                                                                        
end 

这是意外不同的输出:

julia> myarray
2-element Array{Int64,1}:
 0
 0

julia> foo!(myarray);

julia> myarray
2-element Array{Int64,1}:
 0
 0

julia> foobar!(myarray);

julia> myarray
2-element Array{Int64,1}:
 1
 1

如果数组是通过引用传递的,我会期待foo!将零更改为1。

4 个答案:

答案 0 :(得分:19)

r=r+1分配语句,这意味着它会重新分配r,因此它不再引用父作用域中的对。但是r[i]=r[i]+1 变异 r值,变异与赋值(a good description here)不同,之后r仍然引用父范围中的变量对。 / p>

答案 1 :(得分:8)

我认为这里的文件有点模糊。

严格地说,Julia是“按值调用,其中值是参考”,或“按分享调用”,如python,java,ruby,js等大多数语言所使用的...请参阅{ {3}}

按引用行为调用确实会使foo!将零更改为1。然而朱莉娅不支持这一点。 (如果你知道C#,那就是refout所做的)

答案 2 :(得分:1)

在实践中,无论理论(调用by sharing),如前面的答案中所述,一切都发生在Julia中,好像指针变量作为数组传递by reference,而标量变量,如数字,是通过by value

对于像我这样习惯于C语言或Pascal语言的人来说,这是一种痛苦,如果参数是by valueby reference,则在函数声明中的形式参数部分指定。

然而,由于Julia的功能允许在函数中返回多个值,因此有一种优雅的方法来模拟标量变量的参数by reference。显然,这对于像字符串这样的不可变变量也有效,因为变量是重新创建的。

朱莉娅的代码

function process(a,b,c)
  a += c 
  b *= c
  return a*b*c, a, b  # normal result, changing "a" and "b"
end

a = 4
b = 7
println("Before: ", a," ",b)
result, a, b = process(a,b,7)
println("After: ", a," ",b," ", result)

显示

Before: 4 7
After: 11 49 3773 

ab在功能过程中都被更改了。 a已添加到7,b乘以7

答案 3 :(得分:1)

为了改变数组中的每个变量,可以使用广播.操作。但请注意,数组中的每个值都将相同地更改,因此不需要for循环。

在为数组的每个元素添加1的情况下:

a = rand(1:10, 10)
show(a) = [4, 8, 9, 1, 4, 2, 6, 7, 1, 5]

function add1!(a::Array{Int64})
    a .= a .+ 1
end

add1!(a);
show(a) = [5, 9, 10, 2, 5, 3, 7, 8, 2, 6]

尽管如此,如果需要独立更改数组的每个值,那么带有索引的for循环是不可避免的。