How do Julia convert a Expr to another Expr?

How do Julia convert a Expr to another Expr?

g1=:(_+2)

g2=:(x->x+2)

How can I convert g1 to g2?

I know I can do it in this way:


"x->"*replace(string(g1),"_"=>"x") |> Meta.parse

But this way is tedious, I would thought there is a more elegant way?

By the way, my target is to define a maro, which permit pip function with underscore replacing.
More infomation see there:

Is it possible to setdown for this issue in near future?

I find the best way to do Expr manipulation to investigate the expression you have, and the one you want, with dump and then work from there:

julia> dump(:(_ + 2))
Expr
  head: Symbol call
  args: Array{Any}((3,))
    1: Symbol +
    2: Symbol _
    3: Int64 2

julia> dump(:(x -> x + 2))
Expr
  head: Symbol ->
  args: Array{Any}((2,))
    1: Symbol x
    2: Expr
      head: Symbol block
      args: Array{Any}((2,))
        1: LineNumberNode
          line: Int64 1
          file: Symbol REPL[35]
        2: Expr
          head: Symbol call
          args: Array{Any}((3,))
            1: Symbol +
            2: Symbol x
            3: Int64 2

Here is a very simple function to do this transformation. It doesn’t handle complicated inputs (e.g. doesn’t recurse into nested Expr etc) but hopefully it should get you started:

julia> function to_func(ex)
           # Get a unique symbol for the argument
           s = gensym()
           # Replace _ with s
           # TODO: This doesn't handle e.g. nexted Expr etc and needs refinement
           for i in 1:length(ex.args)
               if ex.args[i] === :_
                   ex.args[i] = s
               end
           end
           # Construct return expression
           rex = Expr(:->, s, Expr(:block, ex))
           return rex
       end
to_func (generic function with 1 method)

julia> dump(to_func(:(_ + 2)))
Expr
  head: Symbol ->
  args: Array{Any}((2,))
    1: Symbol ##300
    2: Expr
      head: Symbol block
      args: Array{Any}((1,))
        1: Expr
          head: Symbol call
          args: Array{Any}((3,))
            1: Symbol +
            2: Symbol ##300
            3: Int64 2
3 Likes

That is a more readable function solution, as I can imagine, it is easy to extend for nested Expr.
Thank you so much.