# Forward all function calls on ::MyType to another wrapped field

**URL:** <https://discourse.julialang.org/t/forward-all-function-calls-on-mytype-to-another-wrapped-field/105750>\
**Category:** General Usage\
**Tags:** question\
**Created:** [November 3, 2023, 11:50am UTC](https://discourse.julialang.org/t/forward-all-function-calls-on-mytype-to-another-wrapped-field/105750 "2023-11-03T11:50:48Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [November 3, 2023, 11:50am UTC](https://discourse.julialang.org/t/forward-all-function-calls-on-mytype-to-another-wrapped-field/105750/1 "2023-11-03T11:50:48Z")

</div>

In Julia we cannot inherit from a concrete type. The advice often given to overcome this limitation is to use type composition, i.e. instead of making a type `B` a subtype of a concrete type `A`, wrap an instance of `A` in `B`, and then extend `B` with any extra field you need:

```julia
struct A end
struct B
   a::A
   some_extra_fields
end

```

The problem is that now I would want any function that has been defined on `A` to just work on `B`, by forwarding the wrapped instance. So I would want something like this:

```julia
julia> (f::Function)(b::B, args...) = f(b.a, args...)
ERROR: Method dispatch is unimplemented currently for this method signature
Stacktrace:
 [1] top-level scope
   @ REPL[1]:1

```

So that doesn’t work. Note that a custom Abstract type instead of `Function` does work.

```julia
julia> abstract type MyAbstractType end

julia> (::MyAbstractType)(args...) = 1

```

So my question is twofold:

- Am I “holding it wrong”?
- If this is indeed the intended approach for concrete inheritance, is there a technical reason I cannot extend the methods of abstract type `Function` for my `B` type, so I don’t need to define forwarding methods for each and every function that accepts the wrapped `A`?

(I’m sure there _is_ a technical reason, but then it would be really interesting to know if this limitation could potentially be lifted in the future)

---

<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:** [November 3, 2023, 12:28pm UTC](https://discourse.julialang.org/t/forward-all-function-calls-on-mytype-to-another-wrapped-field/105750/2 "2023-11-03T12:28:14Z")

</div>

If that was possible, how would `B` have a different behavior than `A`? You wouldn’t be able to call even `getfield` on `B`, and thus the extra fields would not be accessible.

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [November 3, 2023, 12:35pm UTC](https://discourse.julialang.org/t/forward-all-function-calls-on-mytype-to-another-wrapped-field/105750/3 "2023-11-03T12:35:04Z")

</div>

You can however use `@eval` to do this automatically with a finite, manually specified list of functions

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [November 3, 2023, 12:41pm UTC](https://discourse.julialang.org/t/forward-all-function-calls-on-mytype-to-another-wrapped-field/105750/4 "2023-11-03T12:41:37Z")

</div>

Oooh, good point about `getfield`. That is a mess indeed.  
Other than `getfield`, I would expect that any _new_ method defined specifically for B (`myfunc(::B) = ...`) would override the less specific `(f::Function)(::B)`

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [November 3, 2023, 12:42pm UTC](https://discourse.julialang.org/t/forward-all-function-calls-on-mytype-to-another-wrapped-field/105750/5 "2023-11-03T12:42:25Z")

</div>

I know, but that’s precisely what I want to avoid, needing to fish functions one by one to put them in an @eval loop. I would need to remember to update this list with any new function I define.

---

<div class="post-metadata">

**Author:** ![adienes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/adienes/32/37459_2.png) [@adienes](https://discourse.julialang.org/u/adienes)\
**Post date:** [November 3, 2023, 1:17pm UTC](https://discourse.julialang.org/t/forward-all-function-calls-on-mytype-to-another-wrapped-field/105750/6 "2023-11-03T13:17:09Z")

</div>

I attempted this once before and my conclusion was it’s basically not possible

---

<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:** [November 3, 2023, 1:22pm UTC](https://discourse.julialang.org/t/forward-all-function-calls-on-mytype-to-another-wrapped-field/105750/7 "2023-11-03T13:22:32Z")

</div>

I don’t know if it is feasible in your case, but you could subtype both A and B on an abstract AorB, and dispatch on it. Then redefine what getfield means for B such that the properties of A are accessible with the same syntax.

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [November 3, 2023, 1:32pm UTC](https://discourse.julialang.org/t/forward-all-function-calls-on-mytype-to-another-wrapped-field/105750/8 "2023-11-03T13:32:35Z")

</div>

Maybe the getfield issue could be solved by making any `(f::Function)(...) = ` definition be the least specific of all possible definitions, respect to method resolution.

---

<div class="post-metadata">

**Author:** ![mhinsch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mhinsch/32/26676_2.png) [@mhinsch](https://discourse.julialang.org/u/mhinsch)\
**Post date:** [November 3, 2023, 1:32pm UTC](https://discourse.julialang.org/t/forward-all-function-calls-on-mytype-to-another-wrapped-field/105750/9 "2023-11-03T13:32:43Z")

</div>

If you are fine with doing some of the work manually you could use [TypedDelegation](https://github.com/JeffreySarnoff/TypedDelegation.jl).

I myself have used it for a while for a project but found it too onerous after a while. I’m now using [CompositeStructs](https://github.com/marius311/CompositeStructs.jl) instead to simply glue the element structs together. This has its own issues (notably in combination with constructors and parametric types), but it’s a workable solution for now.

In general I understand why people advocate composition over inheritance. However, I think there is one use-case that is really difficult to solve (nicely) with composition alone and that’s when a library wants to provide combinable building blocks which can easily be assembled into new structures.

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [November 3, 2023, 1:34pm UTC](https://discourse.julialang.org/t/forward-all-function-calls-on-mytype-to-another-wrapped-field/105750/10 "2023-11-03T13:34:56Z")

</div>

> I don’t know if it is feasible in your case, but you could subtype both A and B on an abstract AorB, and dispatch on it. Then redefine what getfield means for B such that the properties of A are accessible with the same syntax.

The problem is that I don’t own A

---

<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:** [November 3, 2023, 1:36pm UTC](https://discourse.julialang.org/t/forward-all-function-calls-on-mytype-to-another-wrapped-field/105750/11 "2023-11-03T13:36:44Z")

</div>

You can also dispatch on `Union{A,B}` and do not use the abstract type.

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [November 3, 2023, 1:39pm UTC](https://discourse.julialang.org/t/forward-all-function-calls-on-mytype-to-another-wrapped-field/105750/12 "2023-11-03T13:39:50Z")

</div>

Mmm, I admit I don’t see how that solves the “forward any function” problem…

EDIT: clarification, I don’t own `A` or the (large) collection of methods `f(::A)`

---

<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:** [November 3, 2023, 1:57pm UTC](https://discourse.julialang.org/t/forward-all-function-calls-on-mytype-to-another-wrapped-field/105750/13 "2023-11-03T13:57:03Z")

</div>

Oh, I see, I thought you wanted the functions _you_ defined for your new `B` type worked for the not-owned `A` type.

Something like:

```julia
julia> using StaticArrays
       
       struct B
           b::Float64
           vec::SVector{2,Float64}
       end
       
       import Base: getindex
       getindex(b::B, i::Int) = b.vec[i]
       
       const MyTypes = Union{<:SVector, B}
       
       function f(b::MyTypes)
           b[1] + b[2]
       end
f (generic function with 1 method)

julia> f(b)
2.0

julia> f(SVector{2,Float64}(1.0, 1.0))
2.0

```

The other way around I don’t think it is possible, in particular if the method signatures are specific for `A`.

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [November 3, 2023, 2:03pm UTC](https://discourse.julialang.org/t/forward-all-function-calls-on-mytype-to-another-wrapped-field/105750/14 "2023-11-03T14:03:32Z")

</div>

Exactly, that’s the point!

Maybe adding the low-precedence sort of definition of `(f::Function)(...)=...` to Julia, as a new feature, could be possible. It would solve a well defined problem with no current solution. I still don’t know if there is a technical problem with this, or if it is a bad idea for any particular reason…

EDIT: A worry, would this cause invalidations on a massive (maybe catastrophic?) scale?

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [November 3, 2023, 2:24pm UTC](https://discourse.julialang.org/t/forward-all-function-calls-on-mytype-to-another-wrapped-field/105750/15 "2023-11-03T14:24:54Z")

</div>

> [@pablosanjose](#):
>
> Maybe adding the low-precedence sort of definition of `(f::Function)(...)=...` to Julia, as a new feature, could be possible.

This seems like a bad idea. If that worked, then literally every single function in the Julia ecosystem would have a method definition for your wrapper type `B`. The meaning of a type is defined by its behavior, and its behavior is defined by its methods. What does it mean for a type to have a method for literally every single generic function in existence?

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [November 3, 2023, 3:02pm UTC](https://discourse.julialang.org/t/forward-all-function-calls-on-mytype-to-another-wrapped-field/105750/16 "2023-11-03T15:02:30Z")

</div>

Well, if we just forward the wrapped field to `f`, we are simply inheriting the behavior of `A`, not implementing arbitrary new behavior (we would get a MethodError if `f(::A, ...)` is not defined).

However, your comment indeed suggests that `(f::Function)(b::B, args...) = ...` is probably not the correct implementation of behavior inheritance. It should probably be done differently, not through a “abstract Function method”, but something like [`@forward` from MacroTools.jl](https://discourse.julialang.org/t/method-forwarding-macro/23355), but that could somehow work for any function. So

```julia
@forward B.a

```

would have the restricted effect of forwarding `f(b::B, args...)` to `f(b.a, args...)` for any function `f`

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [November 3, 2023, 3:13pm UTC](https://discourse.julialang.org/t/forward-all-function-calls-on-mytype-to-another-wrapped-field/105750/17 "2023-11-03T15:13:26Z")

</div>

some other resources: [GitHub - curtd/ForwardMethods.jl: Composition made easy(ish)](https://github.com/curtd/ForwardMethods.jl)

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [November 3, 2023, 3:25pm UTC](https://discourse.julialang.org/t/forward-all-function-calls-on-mytype-to-another-wrapped-field/105750/18 "2023-11-03T15:25:11Z")

</div>

Thanks @jling , I didn’t know this package. The `@forward_interface` macro is particularly interesting, since it goes about solving this problem through the proper definition of interfaces, i.e. a named collection of function names that one wants to forward.

It does seem like a more sane approach than the “forward anything” idea that I was asking for, which was also @CameronBieganek 's point. So this feels to me like a hole in the design of the Julia type system, which may require a “Taking Interfaces Seriously” github megaissue to get fixed…

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [November 3, 2023, 3:50pm UTC](https://discourse.julialang.org/t/forward-all-function-calls-on-mytype-to-another-wrapped-field/105750/19 "2023-11-03T15:50:19Z")

</div>

As long as the wrapped type has a well defined and reasonably simple interface, then all you need to do is forward the interface methods to the wrapped object and everything else will just work. Here’s an example:

```julia
struct NamedVector{T} <: AbstractVector{T}
    name::Symbol
    x::Vector{T}
end

Base.size(v::NamedVector) = size(v.x)
Base.getindex(v::NamedVector, i) = v.x[i]
Base.setindex!(v::NamedVector, val, i) = (v.x[i] = val)
Base.IndexStyle(::Type{<:NamedVector}) = IndexLinear()

```

Now all this stuff “just works”:

```julia
julia> v = NamedVector(:hello, [3, 2, 1])
3-element NamedVector{Int64}:
 3
 2
 1

julia> map(sqrt, v)
3-element Vector{Float64}:
 1.7320508075688772
 1.4142135623730951
 1.0

julia> sort(v)
3-element Vector{Int64}:
 1
 2
 3

```

So the goal is not to forward all 100 of the functions that work on `A`. The goal is to forward just a few functions that together completely define the behavior of `A`.

(Well, this particular example also relies on making the wrapped type a subtype of `AbstractVector`, but the principle is basically the same.)

---

<div class="post-metadata">

**Author:** ![raythurnevoid](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raythurnevoid/32/52651_2.png) [@raythurnevoid](https://discourse.julialang.org/u/raythurnevoid)\
**Post date:** [December 14, 2023, 3:23am UTC](https://discourse.julialang.org/t/forward-all-function-calls-on-mytype-to-another-wrapped-field/105750/20 "2023-12-14T03:23:34Z")

</div>

This is not good, there’s no way to find what are the methods that “define the behavior of A”. I’m having the same problem of the OP, the issue is the lack of inheritance. i would like to do something like:

```julia
using DataFrames

struct MyDataFrame <: DataFrame end

# override the Base.show implementation
function Base.show(io::IO, mime::MIME"text/plain", df::MyDataFrame)
    show(io, mime, DataFrame(df); allcols=true, allrows=true, eltypes=false)
end

# the constructors should be "inherited"
df = MyDataFrame([...])
typeof(df) # -> MyDataFrame

display(df) # -> calls my custom defined show() above

```

But this doesn’t work.

[Next page](https://discourse.julialang.org/t/forward-all-function-calls-on-mytype-to-another-wrapped-field/105750.md?page=2)
