I struggled a lot to make it work, but in the end I think it’s decent.
julia> macro alajs(ex)
nm = ex.args[1].args[1:(end - 1)]
rest = ex.args[1].args[end].args[1]
r = ex.args[2]
esc(quote
function swap($(r))
($NamedTuple{$(nm...,)}($r)...,Base.structdiff($r,($NamedTuple{$(nm...,)}($r))))
end
$(nm...),$(rest)= swap($(r))
end)
end
@alajs (macro with 1 method)
julia> @alajs (y, rest...) = r
(2, (x = 1, z = 3))
julia> @alajs (z, rest...) = r
(3, (x = 1, y = 2))
julia> @alajs (z, x, rest...) = r
(3, 1, (y = 2,))
julia> @alajs (z, x,y, rest...) = r
(3, 1, 2, NamedTuple())
Compared to the other, it would have the advantage of having specific error indications for NamedTuple
julia> macro alajs(ex)
unpacked = ex.args[1].args[1:(end - 1)]
rest = ex.args[1].args[end].args[1]
rhs = ex.args[2]
return esc(quote
$(unpacked...), $rest = ((;$(unpacked...), $(rest)...) -> ($(unpacked...), (;$rest...)))(;$(rhs)...)
end)
end
@alajs (macro with 1 method)
julia> @alajs (z, x,y,x, rest...) = r
ERROR: syntax: function argument name not unique: "x" around c:\Users\sprmn\.julia\environments
julia> @alajs (z, x,y,w, rest...) = r
ERROR: UndefKeywordError: keyword argument `w` not assigned
julia> macro alajs(ex)
nm = ex.args[1].args[1:(end - 1)]
rest = ex.args[1].args[end].args[1]
r = ex.args[2]
esc(quote
function swap($(r))
($NamedTuple{$(nm...,)}($r)...,Base.structdiff($r,$NamedTuple{$(nm...,)}($r)))
end
$(nm...),$(rest)= swap($(r))
end)
end
@alajs (macro with 1 method)
julia> @alajs (z, x,y,w, rest...) = r
ERROR: type NamedTuple has no field w
julia> @alajs (z, x,y,x, rest...) = r
ERROR: duplicate field name in NamedTuple: "x" is not unique