# Pass through function name to different type

**URL:** <https://discourse.julialang.org/t/pass-through-function-name-to-different-type/45437>\
**Category:** General Usage\
**Created:** [August 23, 2020, 11:50pm UTC](https://discourse.julialang.org/t/pass-through-function-name-to-different-type/45437 "2020-08-23T23:50:37Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![mopg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mopg/32/3368_2.png) [@mopg](https://discourse.julialang.org/u/mopg)\
**Post date:** [August 23, 2020, 11:50pm UTC](https://discourse.julialang.org/t/pass-through-function-name-to-different-type/45437/1 "2020-08-23T23:50:37Z")

</div>

I am making a type that holds another type as one of its fields, like so

```julia
struct A
    a::Float64
end

f(a::A, x::Real) = A.a * x
# plus whole other bunch of functions with similar arguments
g(a::A, x::Real) = ...
h(a::A, x::Real) = ...

struct B
    a1::A
    a2::A
end

```

Now I want the functions that operate on `B` to use the `A` objects inside, depending on the value of `x`, like so

```julia
function f(b::B, x::Real)

    if x >= 0.0
        return f(b.a1, x)
    else
        return f(b.a2, x)
    end

end

```

However, as listed above there are a bunch of functions that operate on `A` with `x` as an input, and it seems cumbersome to copy such a similar function signature many times. So is there a way to pass through the function as well? Something like this (obviously this doesn’t work):

```julia
function (function_name)(b::B, x::Real) where {function_name}

    if x >= 0.0
        return function_name(b.a1, x)
    else
        return function_name(b.a2, x)
    end

end

```

This example above I would only have to write once, and it would work for `f`, `g`, `h`, and any such function that is defined on `A`. Is something like this possible in Julia?

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [August 24, 2020, 12:39am UTC](https://discourse.julialang.org/t/pass-through-function-name-to-different-type/45437/2 "2020-08-24T00:39:26Z")

</div>

I am not sure if I completely understood you problem, but you can pass functions as any other parameter:

```julia
julia> f(a,b) = min(a,b)
f (generic function with 1 method)

julia> g(a,b) = max(a,b)
g (generic function with 1 method)

julia> h(x,y,f) = f(x,y)
h (generic function with 1 method)

julia> h(1,2,f)
1

julia> h(1,2,g)
2

```

---

<div class="post-metadata">

**Author:** ![ettersi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ettersi/32/6829_2.png) [@ettersi](https://discourse.julialang.org/u/ettersi)\
**Post date:** [August 24, 2020, 12:48am UTC](https://discourse.julialang.org/t/pass-through-function-name-to-different-type/45437/3 "2020-08-24T00:48:06Z")

</div>

It sounds like your type `B` is a container for type `A` objects, and applying a function `f` to `B` should apply `f` to each `A` element. Possibly the cleanest way to do so is to use [broadcasting](https://docs.julialang.org/en/v1/manual/arrays/#Broadcasting-1), so you can write `f.(b,x)`.

---

<div class="post-metadata">

**Author:** ![mopg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mopg/32/3368_2.png) [@mopg](https://discourse.julialang.org/u/mopg)\
**Post date:** [August 24, 2020, 1:01am UTC](https://discourse.julialang.org/t/pass-through-function-name-to-different-type/45437/4 "2020-08-24T01:01:25Z")

</div>

Thanks for the replies, I’ll try to clarify a bit.

So I’m trying to find out how to avoid having to write the following code for every function that acts on `A` to also work on `B` (where again, depending on the value of `x`, a different `A` object is selected for the function evaluation):

```julia
function f(b::B, x::Real)

    if x >= 0.0
        return f(b.a1, x)
    else
        return f(b.a2, x)
    end

end

function g(b::B, x::Real)

    if x >= 0.0
        return g(b.a1, x)
    else
        return g(b.a2, x)
    end

end

function h(b::B, x::Real)

    if x >= 0.0
        return h(b.a1, x)
    else
        return h(b.a2, x)
    end

end

```

This code is all so similar, that I figured there would be a way to only write this logic once and have it be applied to every function that acts on `A` (something along the lines of what I wrote in the last code block in my original question).

I think this is a bit different than broadcasting, as I don’t want `f` (and other functions) to simply work on each `A` object inside of `B` but rather use the value of `x` to select which `A` object to use.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [August 24, 2020, 1:18am UTC](https://discourse.julialang.org/t/pass-through-function-name-to-different-type/45437/5 "2020-08-24T01:18:23Z")

</div>

So, one alternative is to pass the function as a parameter:

```julia
function f(b::B, x::Real,func)

    if x >= 0.0
        return func(b.a1, x)
    else
        return func(b.a2, x)
    end

end

```

`func` may be `f`, `g`, `h`, etc.

---

<div class="post-metadata">

**Author:** ![dlakelan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlakelan/32/8491_2.png) [@dlakelan](https://discourse.julialang.org/u/dlakelan)\
**Post date:** [August 24, 2020, 1:32am UTC](https://discourse.julialang.org/t/pass-through-function-name-to-different-type/45437/6 "2020-08-24T01:32:32Z")

</div>

> [@mopg](#):
>
> This code is all so similar, that I figured there would be a way to only write this logic once and have it be applied to every function that acts on `A`

Write a macro that takes a list of function names and writes all this code for you.

---

<div class="post-metadata">

**Author:** ![mopg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mopg/32/3368_2.png) [@mopg](https://discourse.julialang.org/u/mopg)\
**Post date:** [August 24, 2020, 1:45am UTC](https://discourse.julialang.org/t/pass-through-function-name-to-different-type/45437/7 "2020-08-24T01:45:47Z")

</div>

@lmiq: thanks for your reply. I should note that the functions `f`, `g`, `h`, etc are already used throughout the code base, and your suggestion would require changing a bunch of code (wherever `f`, `g`, etc. are called). (That’s my bad, I should’ve made that clear)

@dlakelan: that is a great pointer!

Just to make sure I’m interpreting your answer correctly. You’re suggesting this?

```julia
for op = (:h, :g, :h)
       eval(
              quote
                     function $op(b::B, x::Real)
                            if x >= 0.0
                                   return $op(b.a1, x)
                            else
                                   return $op(b.a2, x)
                            end
                     end
              end
       )
end

```

Are there any problems with that approach in terms of dispatch, type-stability or performance? (or does it simply just generate the code and that’s it?)

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [August 24, 2020, 2:52am UTC](https://discourse.julialang.org/t/pass-through-function-name-to-different-type/45437/8 "2020-08-24T02:52:39Z")

</div>

> [@mopg](#):
>
> Are there any problems with that approach in terms of dispatch, type-stability or performance?

Nope! It’s a perfectly reasonable thing to do.

> [@mopg](#):
>
> or does it simply just generate the code and that’s it?

Yup, exactly. The only downside is that it can make your code harder to read, especially since your text editor or IDE may not be able to figure out where the functions are defined.

---

<div class="post-metadata">

**Author:** ![mopg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mopg/32/3368_2.png) [@mopg](https://discourse.julialang.org/u/mopg)\
**Post date:** [August 24, 2020, 2:59am UTC](https://discourse.julialang.org/t/pass-through-function-name-to-different-type/45437/9 "2020-08-24T02:59:42Z")

</div>

Thanks @rdeits and @dlakelan, this solved my problem!

(I gave @dlakelan the solution as that answer pointed me in the right direction, hope that’s ok. If I could assign the solution to you both, I would)

---

<div class="post-metadata">

**Author:** ![dlakelan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlakelan/32/8491_2.png) [@dlakelan](https://discourse.julialang.org/u/dlakelan)\
**Post date:** [August 24, 2020, 3:10am UTC](https://discourse.julialang.org/t/pass-through-function-name-to-different-type/45437/10 "2020-08-24T03:10:40Z")

</div>

Meta programming is Julia’s secret weapon

---

<div class="post-metadata">

**Author:** ![yha](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yha/32/3502_2.png) [@yha](https://discourse.julialang.org/u/yha)\
**Post date:** [August 24, 2020, 6:37am UTC](https://discourse.julialang.org/t/pass-through-function-name-to-different-type/45437/11 "2020-08-24T06:37:31Z")

</div>

You can write this a bit shorter with

```julia
@eval begin 
   ... 
end

```

replacing `eval(quote .. end)`
