# Macro that generates additional methods of the same function

**URL:** <https://discourse.julialang.org/t/macro-that-generates-additional-methods-of-the-same-function/33873>\
**Category:** General Usage\
**Created:** [January 27, 2020, 8:21pm UTC](https://discourse.julialang.org/t/macro-that-generates-additional-methods-of-the-same-function/33873 "2020-01-27T20:21:40Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![lewis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lewis/32/5217_2.png) [@lewis](https://discourse.julialang.org/u/lewis)\
**Post date:** [January 27, 2020, 8:21pm UTC](https://discourse.julialang.org/t/macro-that-generates-additional-methods-of-the-same-function/33873/1 "2020-01-27T20:21:40Z")

</div>

Here is a macro that works almost as intended:

```julia
macro gen_argfilt(func, tpl)
       return quote
                  function arg_filt(dat::Union{Model_data, Batch_view},nnw::Wgts,
                     hp::Hyper_parameters, bn::Batch_norm_params, hl::Int, fn::typeof($func)); 
                     $tpl
                  end
               end
end

```

The arguments are an existing function and a tuple built up of references to the arguments to the output arg\_filt method. An example is more obvious:

```julia
arg_filt = @gen_arg_filt(relu!,(dat.a[hl], dat.z[hl]))
#113#arg_filt (generic function with 1 method)

```

And you use the output function like this:

```julia
relu!(arg_filt(train, nnw, hp, bn, 1,relu!)...)

```

The effect is to call the function relu! and recast the arguments to match the tuple that was input to the argument. Don’t ask. OK, why? It defers evaluation of the arguments which are giant arrays. To be useful, arg\_filt dispatches on the type of the function.

But, here is the problem. The output of the macro generates funny function names. So, instead of getting new methods of the same function (the function that should be called arg\_filt) each function has a funny name like you see above: `#113#arg_filt`. This is something macros do according to the manual: “Local variables are then renamed to be unique (using the gensym function, which generates new symbols)”.

But, I really want to match the original function name if I run the macro multiple times (which is the whole point). I want a bunch of methods of arg\_filt that dispatch on the typeof(afunc). I don’t know if the macro considers the function definition to be local, which seems to be what triggers gensym. Apparently, I can wrap with esc() to avoid gensym, but I can’t figure out what to escape.

I also tried using function closures. It worked and was straightforward, but ran more than 6x slower. The closure is wildly slow when capturing large arrays, which is a known problem identified in the Performance Tips section of the manual. I tried the suggestions, but they didn’t improve performance.

The obvious work-around, which is what I do NOW (and it works) is to have a bunch of ordinary function definitions for all of the methods in the source code. Nothing wrong here and it is perfectly obvious but there are now 23 method definitions and this will increase. I also want to make it easy for users to create a matching method for their own functions. Since the only difference between them is the name of the function and the tuple, it seemed easy to use a code generation approach.

Here is one such method definition, which makes what the macro is supposed to do a lot more obvious:

```julia
    function argfilt(dat::Union{Model_data, Batch_view}, nnw::Wgts, hp::Hyper_parameters, 
        bn::Batch_norm_params, hl::Int, fn::typeof(sigmoid!))
        (dat.a[hl], dat.z[hl])
    end

```

Basically, the macro should make it easy to create a lot more such methods.

But, for all of these gnarly reasons, it is not so easy at it seemed. Again, sorry this is complex and long but some topics just are that way. I am sorry this is all so complicated, but then nearly anything pertaining to macros is inherently complicated.

I am just looking for a way for the macro to always output a function (e.g., method) with the same exact name every time,

Thanks in advance,  
Lewis

---

<div class="post-metadata">

**Author:** ![lewis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lewis/32/5217_2.png) [@lewis](https://discourse.julialang.org/u/lewis)\
**Post date:** [January 27, 2020, 8:24pm UTC](https://discourse.julialang.org/t/macro-that-generates-additional-methods-of-the-same-function/33873/2 "2020-01-27T20:24:21Z")

</div>

This looks like it might solve it:

```julia
macro gen_argfilt(func, tpl, fname)
       return quote
           function $(esc(fname))(dat::Union{Model_data, Batch_view},nnw::Wgts,
               hp::Hyper_parameters, bn::Batch_norm_params, hl::Int, fn::typeof($func)) 
               $tpl
           end # function
        end # quote block
end # macro definition

```

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [January 27, 2020, 8:58pm UTC](https://discourse.julialang.org/t/macro-that-generates-additional-methods-of-the-same-function/33873/3 "2020-01-27T20:58:43Z")

</div>

The section about “macro hygiene” in the manual is probably useful: [Metaprogramming · The Julia Language](https://docs.julialang.org/en/v1/manual/metaprogramming/#Hygiene-1)
