I worded that poorly, I wasn’t trying to say it was invalid syntax. I ought to have said the syntax doesn’t mean a sequence of single-variable assignments as WalterMadelim expected from let
headers. Under normal circumstances, it is a chained assignment, one of the left-hand expressions doing destructuring assignment:
julia> mutable struct Blah a end
julia> t = Blah(0)
Blah(0)
julia> x = t.a, y = 1:2 # change because integer only has index 1
1:2
julia> x, t, y
(1:2, Blah(1), 2)
let
headers specifying a sequence of assignments or declarations does skew the parsing of otherwise identical text. Here’s an intended destructuring assignment example:
julia> (x, y) = 1:2; x, y
(1, 2)
julia> x, y = 1:2; x, y # we're allowed to omit parentheses here
(1, 2)
julia> let (x, y) = 1:2
x, y
end
(1, 2)
julia> let x, y = 1:2 # parser doesn't play nice anymore
x, y
end
ERROR: UndefVarError: `x` not defined in local scope
In the last erroring example, we don’t even need the assignments in the let
header, and it’d work fine if we move those into the let
body. However, the header necessarily exists to pass values from the outer scope into the let
body the same way a function call passes keyword arguments into a method body:
julia> a = 1;
julia> let a = a # left assigns local a, right accesses value of global a
a+10
end
11
julia> f(;a) = a+10; f(a = a) # same deal here
11
julia> let
a = a # can't use 1 name as 2 variables
a+10
end
ERROR: UndefVarError: `a` not defined in local scope
If it were up to me, I’d further restrict let
headers to simpler assignment expressions to mimick keyword arguments and explicitly describe it that way, but that’d be a breaking change.