# Help with refactoring function into macro

**URL:** <https://discourse.julialang.org/t/help-with-refactoring-function-into-macro/23447>\
**Category:** General Usage\
**Created:** [April 23, 2019, 2:58pm UTC](https://discourse.julialang.org/t/help-with-refactoring-function-into-macro/23447 "2019-04-23T14:58:21Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)\
**Post date:** [April 23, 2019, 2:58pm UTC](https://discourse.julialang.org/t/help-with-refactoring-function-into-macro/23447/1 "2019-04-23T14:58:21Z")

</div>

Hi - yet another help request in regards to macros. I’ve been trying multiple approaches to no avail.

Let’s say I have a code like this:

```julia
module Z 

export z

function z(m = @ __MODULE__ , a='a'; c...)
  "$m :: $a & $(c...)"
end

end

module A 

using ..Z 

z(@ __MODULE__ , 'b', x='x')

end

```

resulting in `"Main.A :: b & :x => 'x'"`

I don’t like how I have to pass `@ __MODULE__ ` when invoking `z` and I would like to write a macro `Z.@z` which uses its ` __module__ ` argument and automatically invokes `z` passing in all the other arguments. So it will be invoked as `@z('b', x='x')` and will return the same `"Main.A :: b & :x => 'x'"`

I tried many approaches, but nothing worked (got an error that macros don’t take keyword arguments, I tried sending an expression and manipulating its args, etc). I find it quite tricky.

Thank you

---

<div class="post-metadata">

**Author:** ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)\
**Post date:** [April 24, 2019, 8:43am UTC](https://discourse.julialang.org/t/help-with-refactoring-function-into-macro/23447/2 "2019-04-24T08:43:01Z")

</div>

No feedback… Wondering if it’s because it’s too simple and I’m missing something… Or too complicated. Curious at least about the best approach, if anybody tried to achieve something similar.

---

<div class="post-metadata">

**Author:** ![mateuszbaran](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mateuszbaran/32/221842_2.png) [@mateuszbaran](https://discourse.julialang.org/u/mateuszbaran)\
**Post date:** [April 24, 2019, 10:03am UTC](https://discourse.julialang.org/t/help-with-refactoring-function-into-macro/23447/3 "2019-04-24T10:03:18Z")

</div>

I think this is more or less what you want:

```julia
module Z 

export @z

function _z(m = @ __MODULE__ , a='a'; c...)
    "$m :: $a & $(c...)"
end

macro z(arglist)
    args = []
    for arg in arglist.args
        if isa(arg, Expr)
            argexpr = :($(esc(arg.args[1])) = $(esc(arg.args[2])))
            argexpr.head = :kw
            push!(args, argexpr)
        else
            push!(args, :($(esc(arg))))
        end
    end
    :(_z($ __module__ , $(args...)))
end

end

module A 

using ..Z 
y = 'x'
w = 'b'

println(@z (w, x=y))

end

```

Does it work for you?

---

<div class="post-metadata">

**Author:** ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)\
**Post date:** [April 24, 2019, 3:06pm UTC](https://discourse.julialang.org/t/help-with-refactoring-function-into-macro/23447/4 "2019-04-24T15:06:03Z")

</div>

@mateuszbaran Thank you, it does!

The problem though is that the syntax is very “unjulian” - one has to pass an invalid tuple as an expression - which is very error-prone. The regular ways of invoking macros, which would be either `@z('b', x='x')` or `@z 'b', x='x'`, both error out. This can be very confusing for a regular user of the API which doesn’t expect that this is, in fact, a special case of an invocation.

I’ve been struggling with this a lot - I’m starting to think that maybe it can’t be done given how the language works.

---

<div class="post-metadata">

**Author:** ![pfitzseb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pfitzseb/32/45566_2.png) [@pfitzseb](https://discourse.julialang.org/u/pfitzseb)\
**Post date:** [April 24, 2019, 3:49pm UTC](https://discourse.julialang.org/t/help-with-refactoring-function-into-macro/23447/5 "2019-04-24T15:49:08Z")

</div>

Do you want something like [this](https://github.com/JunoLab/Traceur.jl/blob/1fe1ccd61e25fbd2cb3766bfb967f492e7499b57/src/trace.jl#L76-L90)?

---

<div class="post-metadata">

**Author:** ![mateuszbaran](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mateuszbaran/32/221842_2.png) [@mateuszbaran](https://discourse.julialang.org/u/mateuszbaran)\
**Post date:** [April 24, 2019, 3:49pm UTC](https://discourse.julialang.org/t/help-with-refactoring-function-into-macro/23447/6 "2019-04-24T15:49:44Z")

</div>

You can also make `@z` accept variable numer of arguments, and `@z('b', x='x')` will work. With some effort, most user errors can be checked for in the macro itself.

---

<div class="post-metadata">

**Author:** ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)\
**Post date:** [April 24, 2019, 4:15pm UTC](https://discourse.julialang.org/t/help-with-refactoring-function-into-macro/23447/7 "2019-04-24T16:15:42Z")

</div>

Thanks for the tip - can’t tell, at first sight, I need to try it out. But it might work, I didn’t realise one can have `@macro(ex, args...)` - I tried with both `@macro(ex)` and `@macro(args...)` but ultimately failed. This might do the trick.

---

<div class="post-metadata">

**Author:** ![essenciary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/essenciary/32/210469_2.png) [@essenciary](https://discourse.julialang.org/u/essenciary)\
**Post date:** [April 24, 2019, 4:16pm UTC](https://discourse.julialang.org/t/help-with-refactoring-function-into-macro/23447/8 "2019-04-24T16:16:25Z")

</div>

Yes, I think it’s what @pfitzseb pointed to, right? Is that what you have in mind? Thanks

---

<div class="post-metadata">

**Author:** ![mateuszbaran](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mateuszbaran/32/221842_2.png) [@mateuszbaran](https://discourse.julialang.org/u/mateuszbaran)\
**Post date:** [April 24, 2019, 4:24pm UTC](https://discourse.julialang.org/t/help-with-refactoring-function-into-macro/23447/9 "2019-04-24T16:24:12Z")

</div>

Yes, something like that 👍.
