> Thank you for the careful explanation and code. It's exactly what I want. I
> have a follow-up question:
>
> 1. I thought I'd make make a (personal) cosmetic modification to your
> `value_dict`.
>
> macro value_dict(vars...)
>     rebindings = [:($(esc(var)) = value($(esc(var)))) for var in vars]
>     quote
>         let $(:($rebindings)...)

`$(rebindings...)` is the simplification you are looking for.
The `...` splat array as multiple argument to the expression. I
believe it is generally as if you replace it with `$(rebindings[1]),
$(rebindings[2]), ...`

>             @symbol_dict($([esc(var) for var in vars]...))
>         end
>     end
> end
>
> It macroexpands into the same code, which is what I want. But I still have
> trouble understanding the $(:($. For example, in a not-macro environment
>
> julia> a = 2
> 2
>
> julia> quote
>        $(:($a))
>        end
> quote  # none, line 2:
>     2
> end
>
> julia> quote
>        (($a))
>        end
> quote  # none, line 2:
>     2
> end
>
> The $ evaluates an expression and : quotes an expression, so I expect
> $(:($a)) to be the same as $a, and indeed it is in this case. But if I try
> to do the same simplification in the let expression, stripping off a shell
> of $(:()),  it macroexpands to
>
> let [:($(Expr(:escape, :a)) = value($(Expr(:escape, :a)))),:($(Expr(:escape,
> :b)) = value($(Expr(:escape, :b))))]...

Seems that you replaced it with `$rebindings`, which removes the
splatting and you splice in an array as the argument to `let`, which
is invalid.

>
> which causes `ERROR: syntax: invalid let syntax`. And I don't quite get why
> they macroexpand differently.
>
> 2. Can `macroexpand` do only one layer (so to speak) of macro expansion? Can
> I do a  `macroexpand(value_dict(x,y))` that still shows the invocation of
> @symbol_dict, without expanding it recursively?

Macros are just functions with a funny name that is called by the
parser. You can call them directly....

julia> macro value_dict(vars...)
           rebindings = [:($(esc(var)) = value($(esc(var)))) for var in vars]
           quote
               let $(rebindings...)
               end
           end
       end
@value_dict (macro with 1 method)

julia> Main.(Symbol("@value_dict"))(:a, :b)
quote  # REPL[1], line 4:
    let $(Expr(:escape, :a)) = value($(Expr(:escape, :a))),
$(Expr(:escape, :b)) = value($(Expr(:escape, :b)))
    end
end

The result doesn't have macro hygiene stuff applied though...


>

Reply via email to