If you’re willing to explicitly mark which symbols should be treated as fields, then this is easier to implement. Here’s a macro which will replace all expressions of the form &a
with container.a
:
julia> using MacroTools: postwalk
julia> macro with(container, expr)
esc(postwalk(expr) do ex
if @capture(ex, &field_)
:(($container).$field)
else
ex
end
end)
end
@with (macro with 1 method)
Usage:
julia> mutable struct Bar
field1
field2
field3
end
julia> b = Bar(1, 2, 0)
Bar(1, 2, 0)
julia> @with b begin
&field3 = &field1 + &field2
end
3
julia> b
Bar(1, 2, 3)
This implementation doesn’t have any problem with local variables which happen to match the names of fields, since the user is responsible (by adding &
) for explicitly marking which symbols should be treated as fields:
julia> field1 = π
π = 3.1415926535897...
julia> @with b begin
# The left-hand side is unambiguously `b.field1`
# and the right-hand side is unambiguously
# the local variable `field1`.
&field1 = field1
end
π = 3.1415926535897...
julia> b
Bar(π, 2, 3)