# Any way to multiple dispatch on functions?\`

**URL:** <https://discourse.julialang.org/t/any-way-to-multiple-dispatch-on-functions/107318>\
**Category:** General Usage\
**Tags:** functions, multidispatch\
**Created:** [December 8, 2023, 8:05am UTC](https://discourse.julialang.org/t/any-way-to-multiple-dispatch-on-functions/107318 "2023-12-08T08:05:38Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jad\_Zeitouni](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jad_zeitouni/32/50678_2.png) [@Jad\_Zeitouni](https://discourse.julialang.org/u/Jad_Zeitouni)\
**Post date:** [December 8, 2023, 8:05am UTC](https://discourse.julialang.org/t/any-way-to-multiple-dispatch-on-functions/107318/1 "2023-12-08T08:05:38Z")

</div>

I defined two abstract types, call them `MyType` and `MyFrozenType{T<:MyType}`.

Subtypes `SpecificFrozenType <: MyFrozenStruct{SpecificType}` are usually defined as `SpecificFrozenType(x::SpecificType, v::Vector)`

Now, I have a series of functions of the form `f(y::SpecificFrozenType)` for different inputs of subtypes of `MyFrozenType`. Is there a way to generically create functions of the form `f(x::T, v::Vector) where T<: MyType = f(SpecificFrozenType(x, v))`.

It’s tedious to rewrite this form for every concrete type, but I’m not sure what’s a more convenient way to do what I want to do.

Edit: I’m adding a MWE to clear up any confusion

```julia
abstract type MyType end
abstract type MyFrozenType{T<:MyType} end

struct Type1 <: MyType end
struct Type2 <: MyType end

struct Frozen1 <: MyFrozenType{Type1} 
    x::Type1
    v::Vector{Float64}
end

struct Frozen2 <: MyFrozenType{Type2}
    x::Type2
    v::Vector{Float64}
end

f(y::Frozen1) = y.v
f(y::Frozen2) = 2 * y.v

f(x::Type1, v::Vector) = f(Frozen1(v))
f(x::Type2, v::Vector) = f(Frozen2(v))

```

What I’m trying to do is not have to type the last two lines for all the types I’m defining.

---

<div class="post-metadata">

**Author:** ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)\
**Post date:** [December 8, 2023, 8:38am UTC](https://discourse.julialang.org/t/any-way-to-multiple-dispatch-on-functions/107318/2 "2023-12-08T08:38:29Z")

</div>

You can generate the code in a loop like this for example:

```julia
for f in (:foo, :bar, :baz, ...)
    @eval $f(x::MyType, v::Vector) = $f(SpecificFrozenType(x, v))
end

```

---

<div class="post-metadata">

**Author:** ![Jad\_Zeitouni](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jad_zeitouni/32/50678_2.png) [@Jad\_Zeitouni](https://discourse.julialang.org/u/Jad_Zeitouni)\
**Post date:** [December 8, 2023, 8:45am UTC](https://discourse.julialang.org/t/any-way-to-multiple-dispatch-on-functions/107318/3 "2023-12-08T08:45:19Z")

</div>

So I should have been clear that `SpecificFrozenType` also changes from function to function. Its the sole concrete type of `MyFrozenType{SpecificType}` for each `SpecificType`.

Also wouldn’t `@eval` affect performance somehow? I’ve always avoided using it in my code. I’m not familiar with metaprogramming at all.

---

<div class="post-metadata">

**Author:** ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)\
**Post date:** [December 8, 2023, 8:49am UTC](https://discourse.julialang.org/t/any-way-to-multiple-dispatch-on-functions/107318/4 "2023-12-08T08:49:00Z")

</div>

Perhaps this then?

```julia
for (f, t) in ((:foo, :SpecificFrozenTypeForFoo), (:bar, :SpecificFrozenTypeForBar), ...)
    @eval $f(x::MyType, v::Vector) = $f($t(x, v))
end

```

> [@Jad\_Zeitouni](#):
>
> Also wouldn’t `@eval` affect performance somehow?

No, the example above is equivalent to

```julia
foo(x::MyType, v::Vector) = foo(SpecificFrozenTypeForFoo(x, v))
bar(x::MyType, v::Vector) = bar(SpecificFrozenTypeForBar(x, v))
...

```

---

<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:** [December 8, 2023, 8:54am UTC](https://discourse.julialang.org/t/any-way-to-multiple-dispatch-on-functions/107318/5 "2023-12-08T08:54:42Z")

</div>

> [@Jad\_Zeitouni](#):
>
> So I should have been clear that `SpecificFrozenType` also changes from function to function

Could you write up a MWE because it’s legitimately confusing which names are proper variables and which names are placeholders for multiple variables. Just write 2 types for the latter, your desired outcome won’t be too large to write out and it’d be clearer what we’re trying to shorten.

---

<div class="post-metadata">

**Author:** ![Jad\_Zeitouni](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jad_zeitouni/32/50678_2.png) [@Jad\_Zeitouni](https://discourse.julialang.org/u/Jad_Zeitouni)\
**Post date:** [December 8, 2023, 9:30am UTC](https://discourse.julialang.org/t/any-way-to-multiple-dispatch-on-functions/107318/6 "2023-12-08T09:30:39Z")

</div>

Apologies. I’ve edited my post with a MWE.

---

<div class="post-metadata">

**Author:** ![Jad\_Zeitouni](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jad_zeitouni/32/50678_2.png) [@Jad\_Zeitouni](https://discourse.julialang.org/u/Jad_Zeitouni)\
**Post date:** [December 8, 2023, 9:37am UTC](https://discourse.julialang.org/t/any-way-to-multiple-dispatch-on-functions/107318/7 "2023-12-08T09:37:28Z")

</div>

I think this is what I want!

So with `@eval` I’m allowed interpolate from symbols into objects with that name? I was always under the impression that `eval()` should be used as a last resort.

What does the `@eval x` do exactly? Is it the same as `eval(x)`?

---

<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:** [December 8, 2023, 9:50am UTC](https://discourse.julialang.org/t/any-way-to-multiple-dispatch-on-functions/107318/8 "2023-12-08T09:50:01Z")

</div>

Excellent example. So you have somewhat of a mapping from `Frozen_` to `Type_` which you can leverage with `typeof(Frozen1instance.x)` or `fieldtype(Frozen1, :x)`, though it’s not good to rely on the field being named `x`. However, you really want a mapping from `Type_` to `Frozen_`, which can be done in methods like those `f` one by one, which a `@eval` loop can help with.

My suggestion would be to decouple those methods from `f` since it looks intended for specific algorithms, so you’d have to do it all over again for say, `g`. Which I guess you can do with another nested `@eval` loop, but the less we put on that the better.

```julia
# must specify one by one
f(y::Frozen1) = y.v
f(y::Frozen2) = 2 * y.v

# 1 method links the type mapping to f
f(x::MyType, v::Vector) = f(freezemytype(typeof(x))(v))

# one by one, pattern can @eval loop
freezemytype(::Type{Type1}) = Frozen1
freezemytype(::Type{Type2}) = Frozen2

# must specify one by one
g(y::Frozen1) = y.v
g(y::Frozen2) = y.v / 2

# 1 method links the type mapping to g
# can @eval loop over f, g, etc
g(x::MyType, v::Vector) = g(freezemytype(typeof(x))(v))

```

> [@Jad\_Zeitouni](#):
>
> What does the `@eval x` do exactly? Is it the same as `eval(x)`

More like `eval(:x)`. Both do `Core.eval(@ __MODULE__ , :x)`, where `@ __MODULE__ ` expands to the enclosing module. `@eval` is just [convenient to save writing](https://docs.julialang.org/en/v1/manual/metaprogramming/#Code-Generation) `(:())` or `(quote end)` around a source code block. If you work with a direct `Expr` instance instead of source code, use the function instead of the macro.
