-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Description
Current behavior
julia> (a, b) = (1, 2, 3) # or `a, b = (1, 2, 3)`
(1, 2, 3)
julia> a
1
julia> b
2I think I'd like an error. This would be breaking on Julia 1.0, but @DilumAluthge suggested I open an issue to keep track of it possibly for Julia 2.0.
As mentioned in the manual, a Tuple can be thought of a positional-argument-only function call without the function. A function call binds values in the calling context to the formal arguments in the function body context, and so it could be nice to have tuple assignment behave more similarly to that binding process. In other words, you cannot call f(a, b) as f(1, 2, 3).
In other words still, if tuple destructuring were more strict, then the two functions g and h would be equivalent (up to error type):
function g(args)
function f(a, b)
a * b
end
f(args...)
end
function h(args)
let (a, b) = args
a * b
end
endjulia> h((2,3))
6
julia> g((2,3))
6
julia> g((2,3,4))
ERROR: MethodError: no method matching (::var"#f#59")(::Int64, ::Int64, ::Int64)
Closest candidates are:
f(::Any, ::Any)
julia> h((2,3,4))
6h((2,3,4)) would throw some kind of error (not MethodError).
This is what happens today:
julia> Meta.@lower (a, b) = c
:($(Expr(:thunk, CodeInfo(
@ none within `top-level scope'
1 ─ %1 = Base.indexed_iterate(c, 1)
│ %2 = Core.getfield(%1, 1)
│ a = %2
│ #s332 = Core.getfield(%1, 2)
│ %5 = Base.indexed_iterate(c, 2, #s332)
│ %6 = Core.getfield(%5, 1)
│ b = %6
└── return c
))))If the strict behavior is desired, I don't know whether to enforce it with a length call, or whether to more generally check that the iterator is empty at the end.