# Macro that construct function names and call them

**URL:** https://discourse.julialang.org/t/macro-that-construct-function-names-and-call-them/130532
**Category:** General Usage
**Tags:** macros
**Created:** [July 7, 2025, 8:45am UTC](https://discourse.julialang.org/t/macro-that-construct-function-names-and-call-them/130532 "2025-07-07T08:45:02Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![jsjie](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jsjie/32/22477_2.png) [@jsjie](https://discourse.julialang.org/u/jsjie)
#### Post date: [July 7, 2025, 8:45am UTC](https://discourse.julialang.org/t/macro-that-construct-function-names-and-call-them/130532/1 "2025-07-07T08:45:03Z")

</div>

My actual usage is that I have a bunch of (~30) functions that performs similar but different operations depending on one argument.

The most straight way to implement is:

```julia
function do!(arg1, l)
    if l == 3
        # do something
    elseif l == 5
        # do something
    # ~30 elseifs
    else
        throw(ArgumentError("Invalid l: $(l)")
    end
end

```

Another way is to implement a bunch of functions `do_n!` and dispatch them:

```julia
const FUNC_DICT = Dict(
    3 => do_3!,
    5 => do_5!,
    # and so on
)

function do_wrapper!(arg1, l)
    if !(l in keys(FUNC_DICT))
        throw(ArgumentError("Invalid l: $(l)")
    end
    FUNC_DICT[l](arg1)
end

```

I wonder whether I can use a macro to perform such dispatch, and I’m found a way:

```julia
macro dis_do(arg1, l)
    return quote Expr(:call, Symbol("do_", $(esc(l)), "!"), $(esc(arg1))) end
end

```

Then I can run `eval(@dis_do(arg1, 3))`  
My question is, can I modify the macro so that the `eval` is not needed?

---

<div class="post-metadata">

### Author: ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)
#### Post date: [July 7, 2025, 9:05am UTC](https://discourse.julialang.org/t/macro-that-construct-function-names-and-call-them/130532/2 "2025-07-07T09:05:07Z")

</div>

Yes and no. With

```julia
macro dis_do(arg1, l)
    return Expr(:call, Symbol("do_", l, "!"), (esc(arg1)))
end

```

you can do `@dis_do(arg1, 3)` but it only works with a literal second argument since macros cannot see argument values (there are no values at the time of macro expansion). I.e., you cannot do

```julia
l = 3
@dis_do(arg1, l)

```

---

<div class="post-metadata">

### Author: ![eldee](https://avatars.discourse-cdn.com/v4/letter/e/b5a626/32.png) [@eldee](https://discourse.julialang.org/u/eldee)
#### Post date: [July 7, 2025, 1:30pm UTC](https://discourse.julialang.org/t/macro-that-construct-function-names-and-call-them/130532/3 "2025-07-07T13:30:34Z")

</div>

> [@jsjie](#):
>
> Another way is to implement a bunch of functions `do_n!` and dispatch them:

Yet another option would be to dispatch on `Val`s:

```julia
function do!(arg1, ::Val{3})
    # (do_3!)
end

function do!(arg1, ::Val{5})
    # (do_5!)
end

...

function do!(arg1, l::Integer) # Specify type of l to avoid infinite recursion on e.g. do!(arg1, 4)
    return do!(arg1, Val(l))
end

do!(..., 3) # equivalent to do_3! call
l = 5
do!(..., l) # equivalent to do_5! call
do!(..., 4) # ERROR: MethodError: no method matching do!(::..., ::Val{4})

```

It’s hard to say which approach would be best, though. In particular, what’s the issue with the original `do!` (`elseif`), or `do_wrapper!` approaches?

---

<div class="post-metadata">

### Author: ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)
#### Post date: [July 7, 2025, 2:07pm UTC](https://discourse.julialang.org/t/macro-that-construct-function-names-and-call-them/130532/4 "2025-07-07T14:07:57Z")

</div>

Generally, I would lean towards the `Dict` approach for its simplicity and extensibility. But there is a lot that can shift that decision.

In most cases an occasional dynamic dispatch is a negligible cost. But if it isn’t (e.g., this function is called many times and the functions it calls are short) and _and your functions all share identical input and output types_ then a tool like FunctionWrappers.jl that can make the dictionary approach above avoid dynamic dispatch. Then it ought to make it perform similarly to the `elseif` chain. Though if the dispatch cost was already negligible then there was nothing to improve.

If you use the dict approach without FunctionWrappers then you might benefit from type-annotating the return value to avoid a type instability cascade. For example, `FUNC_DICT[l](arg1)::typeof(arg1)` if the output type is the same as the input type.

---

<div class="post-metadata">

### Author: ![VinceNeede](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vinceneede/32/215744_2.png) [@VinceNeede](https://discourse.julialang.org/u/VinceNeede)
#### Post date: [July 7, 2025, 4:05pm UTC](https://discourse.julialang.org/t/macro-that-construct-function-names-and-call-them/130532/5 "2025-07-07T16:05:49Z")

</div>

I would not advice that solution, if all the functions are similar but have minor differences, the best thing to do would be to write a major function and then inside call the other functions to which the argument is passed. I think that creating so many different functions, especially inside a macro and the call them, can really be a nightmare in terms of performance, readability, maintainability and debug

---

<div class="post-metadata">

### Author: ![jsjie](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jsjie/32/22477_2.png) [@jsjie](https://discourse.julialang.org/u/jsjie)
#### Post date: [July 8, 2025, 1:35am UTC](https://discourse.julialang.org/t/macro-that-construct-function-names-and-call-them/130532/6 "2025-07-08T01:35:15Z")

</div>

I’m just lazy and think the macro approach might require the minimum typing

---

<div class="post-metadata">

### Author: ![jsjie](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jsjie/32/22477_2.png) [@jsjie](https://discourse.julialang.org/u/jsjie)
#### Post date: [July 8, 2025, 1:45am UTC](https://discourse.julialang.org/t/macro-that-construct-function-names-and-call-them/130532/7 "2025-07-08T01:45:28Z")

</div>

No, functions are not created by the macro, it is only a convenient way to get rid of the lengthy else-ifs. The only difference in the code is to replace each `do!(arg1, l)` with `eval(@dis_do!(arg1, l))`, and everything else is the same. If some `do_x!` function throws an error, in the macro approach the error is also shown clearly.  
That being said, I suppose there will be little difference in readability, maintainability and debug. But I’m not sure whether `eval` will have a great impact on run-time performance.
