Reference Julia函数参数的引用

Reference Julia函数参数的引用,reference,pass-by-reference,julia,Reference,Pass By Reference,Julia,医生说 在Julia中,函数的所有参数都是通过引用传递的 因此,我很惊讶地看到这两个函数的行为有所不同: function foo!(r::Array{Int64})

医生说

在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。

r=r+1
是一个赋值语句,这意味着它重新分配
r
,因此它不再在父范围中引用其对。但是
r[i]=r[i]+1
发生变异r值,变异不同于赋值(),之后
r
仍然在父范围中引用其pair变量。

我认为这里的文档有点模糊

严格地说,Julia是“通过值调用,其中值是引用”,或者“通过共享调用”,大多数语言都使用它,如python、java、ruby、js。。。看


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

在实践中,不管理论如何(通过共享调用
),如前一个答案所述,Julia中的一切都发生在Julia中,就像指针变量作为数组通过引用传递
,而标量变量,如数字,通过值
传递

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

但是,由于Julia的特性允许在函数中返回多个值,因此有一种优雅的方法可以通过引用模拟标量变量的参数
。显然,这甚至适用于字符串等不可变变量,因为这些变量是重新创建的

朱莉娅密码

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 

a
b
在函数过程中都发生了更改
a
被添加到7,而
b
被乘以7

为了变异数组中的每个变量,可以使用广播
操作。但是请注意,数组中的每个值都会发生相同的更改,因此不需要使用
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]

尽管如此,如果一个数组的每个值都需要独立改变,那么<>代码>带有索引的循环是不可避免的。

我也看到了术语“指针调用”(或“指针传递”),用来指这个,我认为这是简短的。无论如何,值得提醒的是,这些术语有时用于语言理论,有时用于实践。而且这些含义并不总是一致的,甚至在一个学科中根据作者的不同而有所不同!“指针值调用”更为清楚,因为它避免了混淆,特别是C++和RIST引用。可以说,调用Julia“通过引用传递”是不正确的,因为它总是通过值传递,如果参数是对象,那么值就是指针。C++、RIST、PL/SQL、SWIFT(和我认为技术上的C和汇编程序)都有能力通过引用,这是一种将指针传递给对象的独特操作。将对象句柄/指针称为“引用”会带来混乱。您可能看到的是更新的版本。他们现在陈述了正确的评估策略(通过共享传递),而不是通过引用传递。