Search code examples
juliametaprogrammingsymbols

julia generate expression with symbol in it


I need to generate an call Expr in which one of the keyword arguments is a symbol. I can type it out explicitly like this:

julia> dump(:(func(something; a=:b)))
Expr
  head: Symbol call
  args: Array{Any}((3,))
    1: Symbol func
    2: Expr
      head: Symbol parameters
      args: Array{Any}((1,))
        1: Expr
          head: Symbol kw
          args: Array{Any}((2,))
            1: Symbol a
            2: QuoteNode
              value: Symbol b
    3: Symbol something

Note the keyword argument a which is set to symbol :b

What I want to do is generate this expression programmatically where the :b part is interpolated from some variable, say x.

I tried this

julia> x = :u
:u

julia> dump(:(func(something; a=$(x))))
Expr
  head: Symbol call
  args: Array{Any}((3,))
    1: Symbol func
    2: Expr
      head: Symbol parameters
      args: Array{Any}((1,))
        1: Expr
          head: Symbol kw
          args: Array{Any}((2,))
            1: Symbol a
            2: Symbol u
    3: Symbol something

but instead of getting a QuoteNode with value Symbol u I just get the Symbol u. This will not work because when I evaluated the expression, it looks for the variable u but it should just be inserting the Symbol u. I have tried some other things but can't get it to work. Thanks


Solution

  • You can wrap x in a QuoteNode manually or use Meta.quot (which produces a Expr(:quote, ...)):

    julia> x = :u;
    
    julia> dump(:(func(something; a=$(QuoteNode(x)))))
    Expr
      head: Symbol call
      args: Array{Any}((3,))
        1: Symbol func
        2: Expr
          head: Symbol parameters
          args: Array{Any}((1,))
            1: Expr
              head: Symbol kw
              args: Array{Any}((2,))
                1: Symbol a
                2: QuoteNode
                  value: Symbol u
        3: Symbol something
    
    julia> func(x; a) = x, a
    func (generic function with 1 method)
    
    julia> eval(:(func(something; a=$(QuoteNode(x)))))
    (something, :u)
    
    julia> eval(:(func(something; a=$(Meta.quot(x)))))
    (something, :u)