1.7 introduced new language feature: (; a, b) = x can now be used to destructure properties a and b of x . This syntax is equivalent to a = getproperty(x, :a); b = getproperty(x, :b)
From a reader perspective(much more compare to writer perspective in action), I can not appreciate the elegance of this syntax. It’s too not “mathematical”.
Existing argument destructuring for tuple is much elegant as there is an isomorphism between the delcare structure and the data structure.
Why this new syntax don’t have this feature?
It does, (; a, b) creates a NamedTuple just as (a, b) creates a Tuple. Note however that just as regular destructuring doesn’t just work with tuples but with any iterable, property destructuring also works with any objects that have fields.
Ah I see your point. But I wouldn’t say it’s like macros: there are arbitrary syntax rules. This follows the rules, while macros allow you to bend the rules.
I think it’s a matter of habit. Probably if we had spent years writing NamedTuple([:a=>1, :b=>2]) we would think (a=1, b=2) is magical, but it’s just new syntax. For me it’s now quite natural to write plot(x, y; linewidth).
It follows the syntax rules because the rules were changed The reason I bring up macros is that it looks like this ought to have a macro in front of it, like @destructure (;a, b) = x or @splat foo(;kw)
What I don’t like about it is that the name choices you make for variables enable special syntax. The syntax wouldn’t work if I wanted to destructure fields :a and :b into variables x and y. Similarly with kwargs.
(BTW, it’s not a big deal, really, but this thread made me come out with it now.)
That would require specifying the source and target names. The main motivation I think was precisely to avoid this repetition when you want to keep the same names.
Having the field specification on the “name binding” side is actually what makes the syntax so useful. Consider these cases:
for (; x, y) in eachrow(df)
println("x-y = $(x-y)")
end
map(eachrow(df)) do (; x, y)
x-y
end
I don’t know how that would work if the syntax was on the “RHS” (meaning eachrow(df) here).
Also I’m not sure you could implement this with a macro. I think it’s really the kind of thing where you need syntax.
I understand the purpose and the advantage, and I have no alternative suggestion to make it work otherwise. It just feels ‘magical’, and I don’t like it, and I wish it wouldn’t work at all, no matter how useful and practical it is.
I don’t dislike it very strongly, but I’m not a fan.
Yes there’s nothing special that DataFrames.jl needs to do: in general (; a, b) = x will do a = x.a and b = x.b. You can write e.g. a = df.a so it works.
This is what the @unpack macro from parameters does and looks like. I use it, but I agree in general with you, one has to be careful to keep the code understandable using that syntax. (I like that @unpack is more verbose, I would like to see that merged into base, but I’m not sure if it can be used everywhere where the new destructuring syntax is used, I guess it does not).