# Proper way to define macros that declare functions?

**URL:** <https://discourse.julialang.org/t/proper-way-to-define-macros-that-declare-functions/104058>\
**Category:** General Usage\
**Tags:** question, macros\
**Created:** [September 20, 2023, 10:21am UTC](https://discourse.julialang.org/t/proper-way-to-define-macros-that-declare-functions/104058 "2023-09-20T10:21:32Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Vincent\_Picaud](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vincent_picaud/32/3108_2.png) [@Vincent\_Picaud](https://discourse.julialang.org/u/Vincent_Picaud)\
**Post date:** [September 20, 2023, 10:21am UTC](https://discourse.julialang.org/t/proper-way-to-define-macros-that-declare-functions/104058/1 "2023-09-20T10:21:32Z")

</div>

I define a `create_foo` macro that declares a function` foo`.

I want to be able to declare `foo` functions in the module where the  
macro is defined.

This part is OK as this minimal example shows:

```julia
  module Foo
  
  macro create_foo(X)
      quote 
	  $(esc(:foo))(x::$(esc(X))) = 2*x
      end 
  end

  println(@macroexpand @create_foo(Int))
  # prints :
  #
  # | begin
  # | #= REPL[7]:4 =#
  # | foo(var"#7#x"::Int) = begin
  # | #= REPL[7]:4 =#
  # | 2var"#7#x"
  # |	end
  # | end
  #
  # which is OK 
  end

```

However, I also want `Foo` module’s users to be able to use this macro to define  
specializations. My problem is that, when calling the macro from `Main` module, I get :

```julia
julia> @macroexpand Foo.@create_foo(Float64)
quote
    #= REPL[7]:4 =#
    foo(var"#9#x"::Float64) = begin
            #= REPL[7]:4 =#
            2var"#9#x"
        end
end

```

The result I want is a fully qualified name:

```julia
julia> @macroexpand Foo.@create_foo(Float64)
quote
    #= REPL[7]:4 =#
    Foo.foo(var"#9#x"::Float64) = begin
            #= REPL[7]:4 =#
            2var"#9#x"
        end
end

```

Does my understanding of the problem is right and how to achieve this expected behaviour ?

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [September 20, 2023, 10:37am UTC](https://discourse.julialang.org/t/proper-way-to-define-macros-that-declare-functions/104058/2 "2023-09-20T10:37:53Z")

</div>

Macros are expanded in the scope that they’re called from, so the name you’re getting actually **is** fully qualified, it’s just not the qualification you expected, since it was called in `Main` instead of `Foo`.

Here’s one way you can get `foo` to always be defined in `Foo`:

```julia
module Foo

macro create_foo(X)
    qualified_name = esc(GlobalRef(Foo, :foo))
    quote 
        $qualified_name(x::$(esc(X))) = 2*x
    end 
end

end

```

```julia
julia> @macroexpand Foo.@create_foo(Int)
quote
    #= REPL[16]:6 =#
    Main.Foo.foo(var"#96#x"::Int) = begin
            #= REPL[16]:6 =#
            2var"#96#x"
        end
end

```

---

<div class="post-metadata">

**Author:** ![Vincent\_Picaud](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vincent_picaud/32/3108_2.png) [@Vincent\_Picaud](https://discourse.julialang.org/u/Vincent_Picaud)\
**Post date:** [September 20, 2023, 10:41am UTC](https://discourse.julialang.org/t/proper-way-to-define-macros-that-declare-functions/104058/3 "2023-09-20T10:41:37Z")

</div>

Great! Thank you for your response.

Creating a function with a macro seems like a fairly common problem to me. Do you have any idea if the way you’re suggesting is the canonical way to solve this problem?

---

<div class="post-metadata">

**Author:** ![skleinbo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skleinbo/32/36080_2.png) [@skleinbo](https://discourse.julialang.org/u/skleinbo)\
**Post date:** [September 20, 2023, 11:08am UTC](https://discourse.julialang.org/t/proper-way-to-define-macros-that-declare-functions/104058/4 "2023-09-20T11:08:26Z")

</div>

May I suggest a function over a macro?

```julia
julia> module Foo

        function foo end

        show_foos() = methods(foo, @ __MODULE__ )

        dosomething() = foo(2.0)

        create_foo(T) = eval(:( foo(x::$T) = 2*x ))
        end
Main.Foo

julia> Foo.create_foo(Int)
foo (generic function with 1 method)

julia> methods(Foo.foo)
# 1 method for generic function "foo" from Main.Foo:
 [1] foo(x::Int64)
     @ REPL[1]:9

julia> Foo.create_foo(Float64)
foo (generic function with 2 methods)

julia> methods(Foo.foo)
# 2 methods for generic function "foo" from Main.Foo:
 [1] foo(x::Int64)
     @ REPL[1]:9
 [2] foo(x::Float64)
     @ REPL[1]:9

julia> Foo.dosomething()
4.0

```

---

<div class="post-metadata">

**Author:** ![Vincent\_Picaud](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vincent_picaud/32/3108_2.png) [@Vincent\_Picaud](https://discourse.julialang.org/u/Vincent_Picaud)\
**Post date:** [September 20, 2023, 11:18am UTC](https://discourse.julialang.org/t/proper-way-to-define-macros-that-declare-functions/104058/5 "2023-09-20T11:18:53Z")

</div>

Thank you. This is a run-time solution, that works too for me.
