IIUC, the following yields the desired behavior:

macro deffun(ex)
    func = ex.args[1]
    args = ex.args[2:end]
    decl = Expr(:call, func, args...)
    body = quote
        # do some stuff                                                     
                                                                            
          
    end
    res = Expr(:function, esc(decl), body)
end

gives

julia> macroexpand(:( @deffun f(x::Int, y::Int) )) 
:(function f(x::Int,y::Int) 
    end)


On Monday, October 19, 2015 at 3:11:11 PM UTC-7, Andrei Zh wrote:
>
> @Kristoffer, as you said, there may be cleaner (more declarative) way to 
> do it, but beyond that your definition works perfectly, thanks! 
>
> On Monday, October 19, 2015 at 2:21:45 PM UTC+3, Kristoffer Carlsson wrote:
>>
>> I am not very good at macros but I took a stap at doing this. It is very 
>> possible this could be done in a cleaner way.
>>
>> Code:
>>
>> macroerror() = throw(ArgumentError("invalid macro expression"))
>>
>> function extract(ex)
>>     if !(ex.head == :call)
>>         macroerror()
>>     end
>>     f_name = ex.args[1]
>>     vars = Symbol[]
>>     types = Symbol[]
>>     for var_ex in ex.args[2:end]
>>         if isa(var_ex, Expr)
>>             if !(var_ex.head == :(::))
>>                 macroerror()
>>             end
>>             sym = var_ex.args[1]::Symbol
>>             typ = var_ex.args[2]::Symbol
>>         elseif isa(var_ex, Symbol)
>>             sym = var_ex
>>             typ = :Any
>>         end
>>         push!(vars, sym)
>>         push!(types, typ)
>>     end
>>
>>     return f_name, vars, types
>> end
>>
>> macro deffun(expr)
>>     f, args, types = extract(expr)
>>     ex = Expr(:function)
>>     ex_def = Expr(:(call))
>>     push!(ex_def.args, f)
>>     for (arg, typ) in zip(args, types)
>>         var_ex = Expr(:(::))
>>         push!(var_ex.args, arg)
>>         push!(var_ex.args, typ)
>>         push!(ex_def.args, var_ex)
>>     end
>>     push!(ex.args, ex_def)
>>
>>     # Function body goes here
>>     ex_body = quote
>>         println("hello")
>>     end
>>
>>     push!(ex.args, ex_body)
>>     return esc(ex)
>> end
>>
>> Usage:
>>
>> julia> @deffun foo(a,b::Int)
>> foo (generic function with 1 method)
>>
>> julia> foo(5, 3.0)
>> ERROR: MethodError: `foo` has no method matching foo(::Int64, ::Float64)
>> Closest candidates are:
>>   foo(::Any, ::Int64)
>>
>> julia> foo(5, 3)
>> hello
>>
>>
>> julia> @deffun bar(a::AbstractString,b::Int)
>> bar (generic function with 1 method)
>>
>> julia> bar("hoho", 3)
>> hello
>>
>>
>>
>> On Monday, October 19, 2015 at 9:45:14 AM UTC+2, Andrei Zh wrote:
>>>
>>> I'm trying to write a macro for generation of new functions given their 
>>> name and arguments, e.g. given macro call: 
>>>
>>> @deffun foo(a, b)
>>>
>>> it should generate function like: 
>>>
>>> function foo(a, b)
>>>     # do some stuff                                                     
>>>                                                                             
>>>                  
>>> end
>>>
>>> Important part is that both - name of a function and name of arguments - 
>>> should be preserved. My best attempt to do it looks like this: 
>>>
>>> macro deffun(ex)
>>>     func = ex.args[1]
>>>     args = ex.args[2:end]
>>>     return quote
>>>         function $(esc(func))($(esc(args...)))
>>>             # do some stuff                                             
>>>                                                                             
>>>                   
>>>         end
>>>     end
>>> end
>>>
>>> `$(esc(func))` works pretty well, but `args` isn't a Symbol and so macro 
>>> compilation fails. 
>>>
>>> 1. How do I escape list of arguments here? 
>>> 2. How do I make this macro to also support argument types? E.g. given 
>>> macro call: 
>>>
>>>
>>> @deffun foo(a::Int, b::Float64)
>>>
>>> the following functions should be generated: 
>>>
>>> function foo(a::Int, b::Float64)
>>>     # do some stuff                                                     
>>>                                                                             
>>>                  
>>> end
>>>
>>>
>>>
>>>

Reply via email to