The docs say
In Julia, all arguments to functions are passed by reference.
so I was quite surprised to see a difference in the behaviour of these two functions:
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
here is the unexpectedly different output:
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
if the array is passed by reference, I would have expected foo! to change the zeros to ones.
r=r+1
is an Assignment statement, this means it reallocates r
, so it no longer refers to its pair in the parent scope. but r[i]=r[i]+1
Mutates r value, mutation is differ from assignment (a good description here), and after that r
still refers to its pair variable in the parent scope.
I think the document is a bit vague here.
Strictly speaking, Julia is "call-by-value where the value is a reference" , or "call-by-sharing", as used by most languages such as python, java, ruby, js... See wiki
A call by reference behaviour would indeed make foo!
to change the zeros to ones. However Julia doesn't support that. (If you know C#, that is what ref
or out
does)
In order to mutate each variable inside an array, the broadcast .
operation can be used. But be aware that each value inside the array will be changed equally thus there is no need for a for
loop.
In the case of adding 1 to each element of an array :
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]
Despite this, if each value of an array is needed to be changed independently then for
loop with indices is inevitable.
In practice, regardless of theory(call by sharing
), described in previous answer, everything happens in Julia as if pointer variables as arrays were passed by reference
, while scalar variables, such as numbers, were passed by value
.
This is a pain for people like me, used to C or Pascal languages, where one specify in formal parameter part in function declaration, if the parameter is by value
or by reference
.
However, due to Julia's feature that allows return of multiple values in a function, there is an elegant way to simulate parameters by reference
for scalar variables. Obviously this works even for immutable variables like strings, since the variables are recreated.
Julia's Code
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)
Display
Before: 4 7
After: 11 49 3773
a
and b
was both changed inside function process. a
was added to 7 and b
was multiplied by 7
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With