Unpacking inside the function assigns into the parent scope; unpacking in the arglist binds a new variable. Should I expect that from something in Scope of Variables · The Julia Language or is that arglist-unpacking a special behavior?
let x = 1
function f(θ)
(;x) = θ
end
θ₀ = (;x=2)
@show x # 1
f(θ₀)
@show x # 2
end
let x = 1
function f((;x))
end
θ₀ = (;x=2)
@show x # 1
f(θ₀)
@show x # 1
end
Which version are you on? They produce the same results on Julia 1.8.2:
julia> VERSION
v"1.8.2"
julia> let x = 1
function f(θ)
(;x) = θ
end
θ₀ = (;x=2)
@show x # 1
f(θ₀)
@show x # 2
end;
x = 1
x = 2
julia> let x = 1
function f((;x))
end
θ₀ = (;x=2)
@show x # 1
f(θ₀)
@show x # 1
end;
x = 1
x = 2
The behavior changed with 1.9.0, but I’m not sure it was on purpose. It isn’t mentioned in the change log. A git bisect turned up
To be fair, while to be expected if one studies the manual thoroughly and grasps the implication of
If a function argument name is written as a tuple (e.g. (x, y)) instead of just a symbol, then an assignment (x, y) = argument will be inserted for you:
in conjunction with the scoping rules, I find the fact that in the latter example, the call f((;x=2)) modifies (rather, used to modify) the parent scope a bit “insane”.
I am glad it has changed, but not too happy about the change being undocumented or possibly unintentional.
I think the 1.8 behavior is correct and the 1.9 behavior is a bug. The 1.8 behavior is just local scoping rules in action. Admittedly it’s less obvious since the assignment is implicit.