# Naming macro and function the same

**URL:** <https://discourse.julialang.org/t/naming-macro-and-function-the-same/117959>\
**Category:** General Usage\
**Tags:** macros, multidispatch\
**Created:** [August 8, 2024, 4:29pm UTC](https://discourse.julialang.org/t/naming-macro-and-function-the-same/117959 "2024-08-08T16:29:28Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![martin\_sanchez](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/martin_sanchez/32/207525_2.png) [@martin\_sanchez](https://discourse.julialang.org/u/martin_sanchez)\
**Post date:** [August 8, 2024, 4:29pm UTC](https://discourse.julialang.org/t/naming-macro-and-function-the-same/117959/1 "2024-08-08T16:29:28Z")

</div>

In the [Source code of Reexport](https://github.com/simonster/Reexport.jl/blob/master/src/Reexport.jl), they define a macro Reexport, inmediately define a behaviour (I assume macros can also have multiple dispatch…?) and then they define a function with the same name:

```julia
macro reexport(ex::Expr)
    esc(reexport( __module__ , ex))
end
    
reexport(m::Module, l::LineNumberNode) = l
    
function reexport(m::Module, ex::Expr)
...

```

Is this also extending the functionality? Does this count as multiple dispatch? Kind of confused with this.

---

<div class="post-metadata">

**Author:** ![jakobjpeters](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jakobjpeters/32/207797_2.png) [@jakobjpeters](https://discourse.julialang.org/u/jakobjpeters)\
**Post date:** [August 8, 2024, 11:36pm UTC](https://discourse.julialang.org/t/naming-macro-and-function-the-same/117959/2 "2024-08-08T23:36:30Z")

</div>

Functions and macros are distinct, so implementing a method for one doesn’t implement a method for the other. In your example, `@reexport` has one method and `reexport` has two. The multiple-dispatch system is being used here in that `reexport` has a method for a `Module` and either a `LineNumberNode` or `Expr`. It might be a bit more noticeable if there were another method where the first parameter wasn’t a `Module`, but many functions don’t have a need to dispatch on multiple parameter types.

```julia-repl
julia> methods(getproperty(Reexport, Symbol("@reexport")))
# 1 method for macro "@reexport" from Reexport:
 [1] var"@reexport"( __source__ ::LineNumberNode, __module__ ::Module, ex::Expr)
     @ ~/.julia/packages/Reexport/OxbHO/src/Reexport.jl:3

julia> methods(Reexport.reexport)
# 2 methods for generic function "reexport" from Reexport:
 [1] reexport(m::Module, ex::Expr)
     @ ~/.julia/packages/Reexport/OxbHO/src/Reexport.jl:9
 [2] reexport(m::Module, l::LineNumberNode)
     @ ~/.julia/packages/Reexport/OxbHO/src/Reexport.jl:7

```

Yes, you can implement methods for macros.

```julia-repl
julia> macro f(::Int) 1 end;

julia> macro f(::String) "two" end;

julia> @f 0
1

julia> @f ""
"two"

```

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [August 8, 2024, 11:50pm UTC](https://discourse.julialang.org/t/naming-macro-and-function-the-same/117959/3 "2024-08-08T23:50:38Z")

</div>

Macros effectively have their own namespace. So there’s no semantic significance to the fact that the names of the function and of the macro are the same.

---

<div class="post-metadata">

**Author:** ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)\
**Post date:** [August 9, 2024, 4:56am UTC](https://discourse.julialang.org/t/naming-macro-and-function-the-same/117959/4 "2024-08-09T04:56:20Z")

</div>

> [@jakobjpeters](#):
>
> Yes, you can implement methods for macros.
> 
> ```julia
> julia> macro f(::Int) 1 end;
> 
> julia> macro f(::String) "two" end;
> 
> julia> @f 0
> 1
> 
> julia> @f ""
> "two"
> 
> ```

Just a word of warning: This only works for literals! The macro generally has no access to the types of a variable. Extending the same example:

```julia
julia> @f 0 # works
1

julia> c = 0
0

julia> @f c # doesn't work
ERROR: LoadError: MethodError: no method matching var"@f"(::LineNumberNode, ::Module, ::Symbol)

```

---

<div class="post-metadata">

**Author:** ![tecosaur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tecosaur/32/23206_2.png) [@tecosaur](https://discourse.julialang.org/u/tecosaur)\
**Post date:** [August 9, 2024, 5:16am UTC](https://discourse.julialang.org/t/naming-macro-and-function-the-same/117959/5 "2024-08-09T05:16:01Z")

</div>

I’d just like to add something lightly cursed to this discussion:

```julia-repl
julia> function var"@hey"(_, _, x) x^2 end
@hey (macro with 1 method)

julia> @hey 4
16

```

---

<div class="post-metadata">

**Author:** ![tecosaur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tecosaur/32/23206_2.png) [@tecosaur](https://discourse.julialang.org/u/tecosaur)\
**Post date:** [August 9, 2024, 5:21am UTC](https://discourse.julialang.org/t/naming-macro-and-function-the-same/117959/6 "2024-08-09T05:21:26Z")

</div>

You can also use this to do things that ~~god~~ Julia never intended 😉

```julia-repl
julia> @generated macro unholy()
       end
ERROR: LoadError: invalid syntax; @generated must be used with a function definition
Stacktrace:
 [1] error(s::String)
   @ Base ./error.jl:44
 [2] var"@generated"( __source__ ::LineNumberNode, __module__ ::Module, f::Any)
   @ Base ./expr.jl:1091
in expression starting at REPL[21]:1

julia> @generated function var"@abomination"(_, _, x)
       @show x; :x
       end
@abomination (macro with 1 method)

julia> @abomination 666
x = Int64
666

```

---

<div class="post-metadata">

**Author:** ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)\
**Post date:** [August 9, 2024, 5:24am UTC](https://discourse.julialang.org/t/naming-macro-and-function-the-same/117959/7 "2024-08-09T05:24:31Z")

</div>

> [@tecosaur](#):
>
> l̴̛̙̭͌̑͛̌̈͊̇͘ị̴̗͚̭̙͐̐̽̎̀͑̎̈ͅg̶̥͓̘̥͔̾́h̶̢̨̯͈̘͙̅̑̐̈̀̈́̎͘t̴̰̬͉͕̮͓́͋͆̊̏̀̋̈́̈́̅ļ̴̗̝͔̖̻́̅̎͋͗͑͒͋͛̎y̷̻̠̭̳̫͔͐̎͛̈́͌͊̔̇̃̓͝ͅ ̷̡̞̘͚̼̰̪̭͌̅͋̒̽͜ͅͅĉ̴͎̾̈́̈́̋̓̒̔̕͝ụ̷̡̩͓̙̰͕͈̝̮̱͂̀̉̓̀̅̋̚r̴̪̱̭̃͒͗ͅs̵̨̹̿͛̂͛̆ę̶̟̖̠̣̳͎͔̔͊̄͛͘͝ͅd̶̬̤̤̪͉̭̉̈̆̾̋͑̚͘͠͝

Pretty sure that this should be illegal 😆

> [@tecosaur](#):
>
> ```julia
> julia> @generated function var"@abomination"(_, _, x)
> @show x; :x
> end
> 
> ```

Oh dear, that’s already twice illegal, since the `@generated` function is not pure 😅  
Sir, we to ask you to stop before future LLMs are trained on your post and then recommend your coding ď̴̠̫͉̼͖̦̜̱̗̐͠e̴̫̻̩͓̦̭͓͙͂ç̵͉͊͗̆̍̀́̔̈́͋͠͝i̵̡̙͂͌̅͛͊̿̉̀ş̷̻̩̘̐̈́͌̿͊i̵̧̛͉̭̠̭̺̪̠͓͂̾̑̍̂̄̐̑̌ȏ̷̭̣̦̯͚̎͂͐ṉ̸̨̹̙̬̌͗͒̾̇̄͝ŝ̵͙̯͆́

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [August 9, 2024, 5:26am UTC](https://discourse.julialang.org/t/naming-macro-and-function-the-same/117959/8 "2024-08-09T05:26:13Z")

</div>

> [@abraemer](#):
>
> The macro generally has no access to the types of a variable.

To clarify, it doesn’t because parsing source code doesn’t reveal anything about the type of a variable, it’s just a `Symbol` at this phase; in addition, you can get `Expr` and the few literal value types. If you’re not just parsing source code though, you can input values with any type, but at that point you have nothing to lose and everything to gain by switching to functions:

```julia
julia> eval(:(@f $c))
"two"

```

You’d only want to interpolate external things into source code in metaprogramming in practice.

> [@tecosaur](#):
>
> ```julia
> julia> function var"@hey"(_, _, x) x^2 end
> @hey (macro with 1 method)
> 
> ```

Yes that’s how macro namespacing is implemented, you can check with `names(m::Module; all=true)`. The name isn’t an exposed detail though, so it may change with minor revisions and shouldn’t be relied on in programs, nor would you ever need to. `macroexpand`, `eval`, and interpolation gives you everything you need to test a macro like a function.

As for the example `reexport` at hand, some macros call an internal function to do almost all the work on the input expression, and that function will often mirror the name. It’s more efficient to call that function directly to test how it affects an `Expr` instead of typing out `macroexpand(@ __MODULE__ , :(@reexport $some_expr))`.
