Metaprogramming function with keyword argument

macros
metaprogramming

#1

I am trying to make a macro that will call a function with certain keyword arguments.

For example,

add(a;b=10) = a+b

Now I can write

z = :(b=20)
parse("add(10,$z)")|>eval

and get the right answer.

But if I write
z = :(b=20)
:(add(10,$z))|>eval

or

:(add(10;$z)|>eval

I don’t get the right answer.


#2

There is a distinction between keywords and assigments:

julia> dump(:(add(10;b=11)))                                                                                                                                             
Expr                                                                                                                                                                     
  head: Symbol call                                                                                                                                                      
  args: Array{Any}((3,))                                                                                                                                                 
    1: Symbol add                                                                                                                                                        
    2: Expr                                                                                                                                                              
      head: Symbol parameters                                                                                                                                            
      args: Array{Any}((1,))                                                                                                                                             
        1: Expr                                                                                                                                                          
          head: Symbol kw                                                                                                                                                
          args: Array{Any}((2,))                                                                                                                                         
            1: Symbol b                                                                                                                                                  
            2: Int64 11                                                                                                                                                  
          typ: Any                                                                                                                                                       
      typ: Any                                                                                                                                                           
    3: Int64 10                                                                                                                                                          
  typ: Any                                                                                                                                                               
                                                                                                                                                                         
julia> dump(:(add(10;$z)))                                                                                                                                               
Expr                                                                                                                                                                     
  head: Symbol call                                                                                                                                                      
  args: Array{Any}((3,))                                                                                                                                                 
    1: Symbol add                                                                                                                                                        
    2: Expr                                                                                                                                                              
      head: Symbol parameters                                                                                                                                            
      args: Array{Any}((1,))                                                                                                                                             
        1: Expr                                                                                                                                                          
          head: Symbol =                                                                                                                                                 
          args: Array{Any}((2,))                                                                                                                                         
            1: Symbol b                                                                                                                                                  
            2: Int64 11                                                                                                                                                  
          typ: Any                                                                                                                                                       
      typ: Any                                                                                                                                                           
    3: Int64 10                                                                                                                                                          
  typ: Any                                                                                                                                                               

do

julia> z = Expr(:kw, :b, 20)                                                                                                                                             
:(b=20)                                                                                                                                                                  

julia> eval(:(add(10;$z)))                                                                                                                                               
30                                                                                                                                                                       

#3

Thanks Mauro! This is a good illustration of just how Expr works.

I also thought I would share: I think that the best way to do what I needed to do is with the splice … syntax. I have a function with a lot of keyword arguments, and I need to loop over different combinations of those and call the function. I hadn’t realized you can splice the keyword arguments like this

add(a=5; b=10, c=12, d=5) = a+b+c+d
params = [[(:b,4)],[(:c,18),(:d,-10)],[(:b,2),(:d,8)]]
[add(;kws...) for kws=ls]