# Automatically generating methods for a specialised struct

**URL:** <https://discourse.julialang.org/t/automatically-generating-methods-for-a-specialised-struct/116455>\
**Category:** General Usage\
**Created:** [July 1, 2024, 5:45am UTC](https://discourse.julialang.org/t/automatically-generating-methods-for-a-specialised-struct/116455 "2024-07-01T05:45:08Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![TimHargreaves](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/timhargreaves/32/207284_2.png) [@TimHargreaves](https://discourse.julialang.org/u/TimHargreaves)\
**Post date:** [July 1, 2024, 5:45am UTC](https://discourse.julialang.org/t/automatically-generating-methods-for-a-specialised-struct/116455/1 "2024-07-01T05:45:08Z")

</div>

Suppose I have the following struct

```julia
struct Foo
    a::Float64
    b::Float64
end

```

that I have defined many methods for.

This is the most general representation, but most of the time I only care about a specialised version where `b = 0.0` (or more generally `b` is any fixed value).

I represent this as a

```julia
struct SpecialFoo
    a::Float64
end

```

I have re-implemented optimised versions for a few of the methods of `Foo` for `SpecialFoo`, but not all methods.

Whenever a method that is defined for `Foo` but not `SpecialFoo` is called, I would like this to automatically be called with a `Foo(SpecialFoo.a, 0.0)`, in a way that has minimal overhead.

I am aware I can manually define this behaviour for a specific function but since I have many methods, I would like it to occur automatically.

I am also aware that I could achieve this by defining an `AbstractFoo` with methods `get_a`, `get_b` which retrieve `a` and `b` for `Foo`, and `a` and `0.0` for `SpecialFoo`, and define all `AbstractFoo` methods in terms of `get_a` and `get_b` but I worry this will quickly become quite messy.

Any thoughts on how I can achieve this would be greatly appreciated.

---

<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:** [July 1, 2024, 6:04am UTC](https://discourse.julialang.org/t/automatically-generating-methods-for-a-specialised-struct/116455/2 "2024-07-01T06:04:10Z")

</div>

I’d avoid making a `SpecialFoo` if you need to bounce back and forth from it. Writing one method with defaults for all positional arguments does make multiple methods with trailing default values, if that’s all you need. `@kwdef` transforms a modified struct expression to include methods with default arguments, but those are keyword arguments, not the positional arguments you described. However, keyword arguments allow defaults to not be all trailing arguments, which is why the macro works on them.

Otherwise, I’d try to make `convert` work from `SpecialFoo` to `Foo`. Or if a specialized method for such a conversion if you prefer.

---

<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 1, 2024, 6:15am UTC](https://discourse.julialang.org/t/automatically-generating-methods-for-a-specialised-struct/116455/3 "2024-07-01T06:15:55Z")

</div>

It sounds like something you can achieve with an `@eval` loop, cf. the manual section on [code generation](https://docs.julialang.org/en/v1/manual/metaprogramming/#Code-Generation).

> [@TimHargreaves](#):
>
> define all `AbstractFoo` methods in terms of `get_a` and `get_b` but I worry this will quickly become quite messy

If it’s just the spelling of the getters that would make things messy, you could consider [getproperty overloading](https://docs.julialang.org/en/v1/base/base/#Base.getproperty).

---

<div class="post-metadata">

**Author:** ![TimHargreaves](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/timhargreaves/32/207284_2.png) [@TimHargreaves](https://discourse.julialang.org/u/TimHargreaves)\
**Post date:** [July 2, 2024, 8:38am UTC](https://discourse.julialang.org/t/automatically-generating-methods-for-a-specialised-struct/116455/4 "2024-07-02T08:38:05Z")

</div>

> [@Benny](#):
>
> Writing one method with defaults for all positional arguments does make multiple methods with trailing default values, if that’s all you need.

Thank you for the reply!

I might not be understanding you correctly or maybe I didn’t explain myself clearly enough, so I will clarify. I need `SpecialFoo` for dispatching versions of the usual methods that are optimised for the `b=0.0` case.

I think (again, I might not be following) you’re are suggesting have kwarg constructors for `Foo` so that I can set `b=0.0` but then I can’t dispatch on this fact.

> [@Benny](#):
>
> Otherwise, I’d try to make `convert` work from `SpecialFoo` to `Foo`.

This sounds much closer to what I’m after. I can see what this `convert` method would look like and how to use it in a one-off case:

`f(x::SpecialFoo) = f(convert(Foo, x))`

but not how I could make that automatically apply for all possible functions.

---

<div class="post-metadata">

**Author:** ![TimHargreaves](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/timhargreaves/32/207284_2.png) [@TimHargreaves](https://discourse.julialang.org/u/TimHargreaves)\
**Post date:** [July 2, 2024, 8:41am UTC](https://discourse.julialang.org/t/automatically-generating-methods-for-a-specialised-struct/116455/5 "2024-07-02T08:41:29Z")

</div>

> [@GunnarFarneback](#):
>
> It sounds like something you can achieve with an `@eval` loop, cf. the manual section on [code generation](https://docs.julialang.org/en/v1/manual/metaprogramming/#Code-Generation).

This sounds like a good approach if no “built-in” approach exists. I will look into this. Thanks!

> [@GunnarFarneback](#):
>
> If it’s just the spelling of the getters that would make things messy, you could consider [getproperty overloading](https://docs.julialang.org/en/v1/base/base/#Base.getproperty).

Yes, I think the added getter calls cluttering up the code was my concern. The getproperty overloading is a nice workaround, though I think I recall reading elsewhere that it isn’t often considered best practice—I’m sure how seriously I should be taking that warning.

Thanks for sharing your ideas!

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [July 2, 2024, 9:41am UTC](https://discourse.julialang.org/t/automatically-generating-methods-for-a-specialised-struct/116455/6 "2024-07-02T09:41:14Z")

</div>

> [@TimHargreaves](#):
>
> I am also aware that I could achieve this by defining an `AbstractFoo` with methods `get_a`, `get_b` which retrieve `a` and `b` for `Foo`, and `a` and `0.0` for `SpecialFoo`, and define all `AbstractFoo` methods in terms of `get_a` and `get_b` but I worry this will quickly become quite messy.

I’ve had a similar problem once. I solved it with such an AbstractFoo, but not with `get_a` and `get_b`, but by defining a `b` property on `SpecialFoo`.

```julia
function Base.getproperty(obj::SpecialFoo, s::Symbol) 
   (s==:b) ? zero(obj.a) : getfield(obj, s)
end

```

It’s a somewhat dirty hack which can be used in simple cases.
