起因
我之前一直没有搞懂 Julia 的参数到底是怎么传的(自然 Python 我也就没有懂),不知道何时会改变参数的值,何时不会。最近在学 C语言,明显感到传参很清晰,就是传值,要改变函数外面的对象,就传指针进去。因此为了搞懂 Julia 到底是怎么传参数的(我以前有些函数写得莫名其妙,因为不知道会不会改变传入的对象),又去翻了文档,可惜没看懂。
Julia 函数参数遵循有时称为 “pass-by-sharing” 的约定,这意味着变量在被传递给函数时其值并不会被复制。函数参数本身充当新的变量绑定(指向变量值的新地址),它们所指向的值与所传递变量的值完全相同。调用者可以看到对函数内可变值(如数组)的修改。这与 Scheme,大多数 Lisps,Python,Ruby 和 Perl 以及其他动态语言中的行为相同。
尝试
当我尝试去搜索 pass-by-sharing
的时候,其实并没有太合适的结果,直到昨天,我又一次去搜索,点进有可能的结果里面一个个看,看到了 这篇文章 深入探討 JavaScript 中的參數傳遞:call by value 還是 reference?, 就有点懂了,发现叫 call by sharing
. 最后一下就搜索出来了。(现在再次搜索发现是我把第一个搜索结果 Evaluation strategy 给忽略了,它里面基本上讲明白了。 )
我的理解
看了文章与 wiki 之后感觉有点明白了。我的理解是这样的,不知道对不对。
如果是对对象整体进行的操作,就不会改变原始的对象,但是如果是直接修改对象的部分,就会改变原来的对象。
举例
x=reshape(collect(1:9),3,3)
function f(x)
x=x^2
end
println(f(x)) #[30 66 102; 36 81 126; 42 96 150]
println(x) #[1 4 7; 2 5 8; 3 6 9]
此处 x
不变,是因为 函数内的 x
和外面的 x
共享同一个对象,后来 x=x^2
给函数内的 x
重新赋值,它不再共享函数外面的 x
的那个对象, 我们也没有修改那个对象。因此,外面的 x
没有改变。
用指针的思路来理解的话,就是 函数内的 x
确实指向 函数外的 x
的那个对象,但是在 x=x^2
这里,它指向了中间生成的临时变量 x^2
, 不再指向函数外部的 x
. 因此 函数外部的 x
不变。
x=reshape(collect(1:9),3,3)
function g(x)
x.=x^2
end
println(g(x)) #[30 66 102; 36 81 126; 42 96 150]
println(x) #[30 66 102; 36 81 126; 42 96 150]
这里我的理解是,x^2
生成了一个新的矩阵, 然后 x .= x^2
相当于是
y=x^2
for i in eachindex(x)
x[i]=y[i] # 这里按位置修改了 x的值。
end
这里,我们直接修改了函数内的 x
所共享的对象,由于函数内外的两个 x
共享同一个对象,因此外面的 x
也被改变了。
按照指针的思路来理解的话,就是我们先创建了一个临时变量 y=x^2
, 然后通过指针,将 x
上的值一个个变成y
的值。最后 函数外的x
自然就变了。
写在最后
以上是个人理解,感觉其实并不是十分准确,希望有明白的人能够再讲的细一点。这样我就知道,我到底什么时候该给函数加上!
了(因为有时候函数并不按照我想的那样修改了参数的值。)