Let-in macro

I want a macro like this:

@let begin
a = 1
b = 2
in
y = a + b
z = a - b
end

defines in the containing scope y and z in terms of a and b, without defining a and b in the containing scope. How can I do this?

Do you know about let blocks?

https://docs.julialang.org/en/v1/manual/variables-and-scoping/#Let-Blocks

A let block can do this but the names x and y are far away from their values which makes it harder to read and easier to get out of synch.

x, y = let
    a = 1
    b = 2
    a + b, a - b
end

You can return a NamedTuple from the let block and destructure it for the assignment:

julia> (; x, y) = let a = 1, b = 2
           (x = a + b, y = a - b)
       end
(x = 3, y = -1)

julia> x
3

This thread seems to have wandered off from your original question. What specifically about authoring this macro do you need help with?

You can do this instead, if you want y and z to be available outside, but not a and b:

begin
    local a = 1
    local b = 2
    y = a + b
    z = a - b
end

What should this macro be translated into?

When designing macros, there are in general two questions one needs to answer:

  • What expressions are valid for that macro?
  • How should the result look like?

Four your example I think a valid expression for your @let macro might look like this:

  • Its a :block expression, and
  • one of its lines consists just of the symbol :in, and
  • all of the lines before that are simple assignments of the form <varname> = ...

But what should this do, what should it turn into? Do you want the result to look like this?

z, y = let a=1, b=2
    y = a + b
    z = a - b
    z, y
end