Of course, that whole bit with decl is unnecessary:

julia> macro deffun(ex)
           body = quote
               x + y
           end
           res = Expr(:function, esc(ex), body)
       end

julia> @deffun f(x::Int, y::Int)
f (generic function with 1 method)

julia> methods(f)
# 1 method for generic function "f":
f(x::Int64, y::Int64) at none:3

julia> f(1, 2)
3

On Tuesday, October 20, 2015 at 11:19:44 AM UTC-7, David Gold wrote:
>
> 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