# What's the best practice to avoid forcing users into adding specific fields of their struct?

**URL:** https://discourse.julialang.org/t/whats-the-best-practice-to-avoid-forcing-users-into-adding-specific-fields-of-their-struct/55751
**Category:** Internals & Design
**Tags:** struct
**Created:** [February 22, 2021, 12:06am UTC](https://discourse.julialang.org/t/whats-the-best-practice-to-avoid-forcing-users-into-adding-specific-fields-of-their-struct/55751 "2021-02-22T00:06:47Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![iHany](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ihany/32/18151_2.png) [@iHany](https://discourse.julialang.org/u/iHany)
#### Post date: [February 22, 2021, 12:06am UTC](https://discourse.julialang.org/t/whats-the-best-practice-to-avoid-forcing-users-into-adding-specific-fields-of-their-struct/55751/1 "2021-02-22T00:06:48Z")

</div>

I’d like to user-friendly interface in my simulator.  
So, I don’t wanna force users to add some specific struct fields.

However, I encountered some issues in my usage pattern.  
For example, `FymEnv` is a type given by my package, and `Env` will be user-defined struct.  
`f` (meaning update proceduer in simulator) will be the user-defined function for simulation. `integral` is provided by the package.  
I’d like to _record_ `Env`’s property (=env’s `size`, namely) once (which can be calculated at the beginning of simulation) and reuse it to enhance simulation performance.  
Here is that looks like what I want:

```julia
struct Env <: FymEnv
    a # something
end
function f(env::Env)
    a = env.a
    integral(env) # how to refer its size inside `integral` without attaching field `size`?
    return a # just an illustrative example
end

```

However, `integral` requires env’s size and calculate it at every instant may make the performance bad.  
Of course, I may force users to add field `size` to their struct `Env` but it’s quite annoying to me because the envs. can be very large and nested.  
On the other hand, if I provide another struct (`FymSym`, namely) as follows,

```julia
struct Sim <: FymSym
    env::Env
    size
end

```

users have to consider it and change the function `f` like

```julia
function f(sim::FymSym)
    a = sim.env.a # annoying
    integral(sim) # can get size by `sim.size` inside `integral`
    return a # just an illustrative example
end

```

If there any good idea to solve it?

For more details, this issue is originally from avoiding exhausted calculation of the size of state, addressed in [LazyFym.jl](https://github.com/JinraeKim/LazyFym.jl).

---

<div class="post-metadata">

### Author: ![ToucheSir](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/touchesir/32/14411_2.png) [@ToucheSir](https://discourse.julialang.org/u/ToucheSir)
#### Post date: [February 22, 2021, 12:24am UTC](https://discourse.julialang.org/t/whats-the-best-practice-to-avoid-forcing-users-into-adding-specific-fields-of-their-struct/55751/2 "2021-02-22T00:24:17Z")

</div>

Why not simply have a function `a` (or a longer name if “a” is too short) that can be implemented for each env? This kind of getter pattern is both idiomatic and works around you having to know where `a` is located on each type.

---

<div class="post-metadata">

### Author: ![iHany](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ihany/32/18151_2.png) [@iHany](https://discourse.julialang.org/u/iHany)
#### Post date: [February 22, 2021, 12:27am UTC](https://discourse.julialang.org/t/whats-the-best-practice-to-avoid-forcing-users-into-adding-specific-fields-of-their-struct/55751/3 "2021-02-22T00:27:31Z")

</div>

If you mean `a(env::Env) = env.a`, then I don’t understand how it solves this problem.

Can you give me a detailed example?

---

<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: [February 22, 2021, 1:00am UTC](https://discourse.julialang.org/t/whats-the-best-practice-to-avoid-forcing-users-into-adding-specific-fields-of-their-struct/55751/4 "2021-02-22T01:00:27Z")

</div>

Not quite-- the whole idea is that you instruct your users to define the `YourPkg.a()` function for their particular type. Then you can write generic functions in terms of this `a()` function, and your code will work with any type which has defined a method for `a()`, regardless of its particular fields.

This is how nearly every interface in Julia works, so I’d suggest looking here for some real-life examples: [Interfaces · The Julia Language](https://docs.julialang.org/en/v1/manual/interfaces/#Indexing)

---

<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: [February 22, 2021, 6:11am UTC](https://discourse.julialang.org/t/whats-the-best-practice-to-avoid-forcing-users-into-adding-specific-fields-of-their-struct/55751/5 "2021-02-22T06:11:00Z")

</div>

You’re right, defining `a(env::Env) = env.a` just to use `a(env1)` instead of `env1.a` seems redundant, but it gets really convenient for more complicated types. For `Sim`, you can define `a(sim::Sim) = sim.env.a`, so `a(sim1)` works. You can then feed both `Env` and `Sim` into the same method that calls `a`:

```julia
function f(x)
    y = a(x)
    # rest of code #
end

```

It even works on types with no `a` field. Let’s say you have a struct `A1sauce` where a hypothetical `a` value should always be 1. It’s a waste of memory to add an `a` field just to store a 1 there for every instance. Just define `a(::A1sauce) = 1`.

---

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [February 22, 2021, 7:01am UTC](https://discourse.julialang.org/t/whats-the-best-practice-to-avoid-forcing-users-into-adding-specific-fields-of-their-struct/55751/6 "2021-02-22T07:01:33Z")

</div>

> [@Benny](#):
>
> a(sim::Sim) = sim.env.a

Or, maybe preferably, `a(sim::Sim) = a(sim.env)`. Then the outer function doesn’t need to understand how `env` is structured.
