Struct Destructuring in Julia
Two days ago LWN published my article about the new features arriving with version 1.7 of Julia. One new syntax feature that I only had space to treat briefly is a new form of destructuring. Here I want to explain in more detail why this can be useful.
In Julia you can define a struct like this:
struct S
a
b
end
This is usually how we define new datatypes.
If we instantiate the struct with newS = S(4, 5)
, we can access the two properties of newS
with newS.a
and newS.b
, which yield 4 and 5. This is existing syntax.
The new feature allows us to destructure this way:
(; a, b) = newS
Now a
has the value 4 and b
has the value 5.
The field names on the left must exist in the struct. Otherwise, you get an error:
(; a, x) = newS
ERROR: type S has no field x
This might seem at first glance to be of limited utility. In current Julia, you can already do this:
a, b = newS.a, newS.b
So the new syntax is a bit more concise.
However, the real advantage of the new destructuring may be in providing a succinct way to define functions that take keyword arguments.
The standard way to define a function that takes, say, one positional argument and two keyword arguments a
and b
is like this:
f(d; a, b) = (a + b)/d
And you call it with f(2; a=3, b=4)
, which yields 3.5.
But in the next version of Julia we can define it this way:
f2(d, (; a, b)) = (a + b)/d
This looks like it takes two positional arguments, but consider what happens if we make the call
f2(2, newS)
When the function interprets its arguments, d
will get the value 2, and (; a, b)
will get the value newS
; but, with the new destructuring, this will assign 3 to a
and 4 to b
, so it’s the same as calling f(2; a=3, b=4)
. We can store other values for a
and b
in different instantiations of S
, and pass them in to f2
as needed.
The new syntax can aid expressiveness, especially if you want to create a function that takes many keyword arguments. In practice, you may want to ensure that the struct you pass in has the right type by defining f2
this way:
f2(d, (; a, b)::S) = (a + b)/d
As I work on my Julia book I revisit completed chapters to update them with useful new features in the language and various packages as they come out or get close to release. In this way I hope that it will be as up-to-date, when it arrives, as a print book can be.