看julia学习文档时,在函数篇有提到julia的参数是通过值不是引用值,我没有看懂这是什么意思,两者有什么区别。
尝试解答一下,不一定对,
a = 1; 这个时候创建了一个Int-1的对象,a就是个名字,指向这个对象。
b = a;b 也指向了这个Int-1对象。
a = 2; 创建了一个Int-2的对象,这个时候a就指向了Int-2。注意上面那个Int-1对象还在。
这与C不一样(想想一下C中,变量是绑定了一个内存地址,一开始该内存为1,你给a赋值,就是改变这个内存的值为2了)
那好了,只要是变量赋值操作left = right, right要不是创建一个对象就是指向一个对象,=就是将该对象与左边的变量联系起来。
好了,现在假设一个函数
function f(x)
x = 5
end
,这里我觉得就不要纠结形参与实参问题,就是x是函数f的局部变量,
f(a)即为f(x=a)
就是把a指向的Int-2的对象与x联系起来了,此时x和a都指向Int-2。
执行到 x = 5时, 创建了一个Int-5对象,x指向Int-5,那原来的a呢,它还是指向Int-2.
由此可以看出,函数传的是对象的把柄。但是你不能向c一样改变原来的a变量值。这里一定要理解‘=’是建立一个对象和一个变量的联系。把对象的把柄用交给左边的变量
还有个问题,对于数组之类的
function f(x::Array{Int, 1})
push!(x, 5)
x = [1, 2]
end
arr = [1,2,3]; 创建了[1,2,3]数组对象,arr指向它
f(arr) 同样是把arr引用传给x, 它两指向相同的对象,push!(x, 5),将这个对象后面5,
这个时候外面arr 和x 都指向 [1,2,3,5],
执行x = [1, 2] 时, x就改指向 [1, 2],但是arr指向的对像没有被修改。
最后,唠叨一下
1、Julia(或者python)创建的对象分为不可变和可变的两种
不可变的如Int-1,它在内存某个地方创建了(无须关心它在什么地址),它就是1,你改变不了它。
可变的如Array-[1,2,3],你能改变它,比如你可以把第一个数改成5,或者后面加个数。
2、对于Python和Julia,就不要想着传值和传引用, 什么都是对象,对象有个柄(handle),变量就是抓这个柄(等号就是抓柄),如果没人抓,它就的被回收。如果变量var抓住一个不可变对象,var只能用它,不能改变它,想要改变它就得重新抓个对象。
乱糟糟的,作为新手自己领悟的。
可以说一下具体是哪里么?
http://docs.juliacn.com/latest/manual/functions/
使用call by sharing的语言,=
既可以表示赋值操作(本质是变量名绑定,也可以表示mutation操作。(如有疑问,推荐参考Stefan的这个回答:Creating copies in Julia with = operator - Stack Overflow
在参数传递时,相当于是在被调用者的scope中进行了新的变量名绑定:
a, b = 1, 2.0
function foo(x::Int, y::Float64)
x = 3
x + y
end
# 执行
foo(a, b)
# 相当于在foo的scope中,进行了赋值(绑定)操作`x = a`, `y=b`
# 这时变量名`x`被绑定到了变量名`a`被绑定到的那个值,也就是1
# 变量名`y`被绑定到了变量名`b`被绑定到的那个值,也就是2.0
然后,在foo
内部执行x=3
时,x
被重新绑定(rebind)到了值3,而a
的绑定仍然是1
。从外部看,这个行为与C/C++中的传值(call by value)一致。而C/C++中的”传引用“的这个行为在call by sharing的语言中是用mutation操作实现的,必须要求输入变量是mutable类型的。
(个人观点)在call by sharing的语言中,最好只说 binding 和 mutation, 而不要用传引用,传值这些说法,以便引起不必要的误解。