# How to enforce function signature type on a struct

**URL:** <https://discourse.julialang.org/t/how-to-enforce-function-signature-type-on-a-struct/101211>\
**Category:** New to Julia\
**Created:** [July 5, 2023, 1:15pm UTC](https://discourse.julialang.org/t/how-to-enforce-function-signature-type-on-a-struct/101211 "2023-07-05T13:15:23Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![nickk2002](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nickk2002/32/202480_2.png) [@nickk2002](https://discourse.julialang.org/u/nickk2002)\
**Post date:** [July 5, 2023, 1:15pm UTC](https://discourse.julialang.org/t/how-to-enforce-function-signature-type-on-a-struct/101211/1 "2023-07-05T13:15:23Z")

</div>

Hi julia community!

I am working on a program synthesis library for julia. We represent the algorithms as iterators that enumerate the search space of possible programs in a certain order. Algorithms might need certain configuration to run. For instance, genetic algorithms need a `cross_over` function and a `mutate!` function.

What would be a good way to enforce the signature of the `cross_over` function for instance?  
The function should have a certain signature and certain return type. If a user provides the wrong function an error should be thrown before the algorithm even starts.

If it is not possible to provide the exact signature type for the function, what would be a better way to design the code? I remember reading a post where someone said that storing functions in a struct is not the best idea.

```julia
Base.@kwdef struct GeneticSearchIterator <: ExpressionIterator
    fitness::Function
    cross_over::Function # cross over two parents
    mutation!::Function # mutates a node
    mutation_probability::Float64
    evaluation_function::Function
end

```

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/224680_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [July 5, 2023, 1:35pm UTC](https://discourse.julialang.org/t/how-to-enforce-function-signature-type-on-a-struct/101211/2 "2023-07-05T13:35:26Z")

</div>

The answer is that you can’t, because a “function” in Julia is just a name given to a collection of “methods”, which are the [actual implementations](https://docs.julialang.org/en/v1/manual/methods/#Methods) for each combination of input types.  
The type of a function `f` is just `typeof(f)`, and it doesn’t give you any clues on what the function eats or spits out, precisely because 2 methods of `f` might behave differently.  
Just think of all the implementations available for addition, which you can list by running `methods(+)`.

As a result, it is impossible to do what you want _statically_, i.e. based only on the type of the `cross_over` function.  
You can however do it _dynamically_ when you call `cross_over`, simply by checking that the outputs are what you expect, and throwing an error if they are not.

Side note: since each function has a unique type, the way you wrote your struct means it will be very inefficient because the compiler cannot recognize the functions it contains.  
In other words, you used a [container with a field of abstract type](https://docs.julialang.org/en/v1/manual/performance-tips/#Avoid-fields-with-abstract-type).  
It’s a common mistake, and here is how to fix it: encode the type of each function in the [type parameters](https://docs.julialang.org/en/v1/manual/types/#Parametric-Types) of the struct.  
The documentation should probably mention this special case.

```julia
Base.@kwdef struct GeneticSearchIterator{F1,F2,F3,F4} <: ExpressionIterator
    fitness::F1
    cross_over::F2 # cross over two parents
    mutation!::F3 # mutates a node
    mutation_probability::Float64
    evaluation_function::F4
end

```

Note that the `Fi`s could be forced to subtype `Function`, but this would be counterproductive, since there are [other things than functions](https://docs.julialang.org/en/v1/manual/methods/#Function-like-objects) which behave in the same way, that is, which you can call.

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/224680_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [July 5, 2023, 1:47pm UTC](https://discourse.julialang.org/t/how-to-enforce-function-signature-type-on-a-struct/101211/4 "2023-07-05T13:47:05Z")

</div>

> <https://github.com/JuliaLang/julia/pull/50421>
>
> The following pattern is very common among beginners:
> 
> \`\`\`julia
> struct MyStru…ct
> f::Function
> end
> \`\`\`
> 
> This PR advises against it
> 
> https://discourse.julialang.org/t/how-to-enforce-function-signature-type-on-a-struct/101211/2

---

<div class="post-metadata">

**Author:** ![nickk2002](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nickk2002/32/202480_2.png) [@nickk2002](https://discourse.julialang.org/u/nickk2002)\
**Post date:** [July 5, 2023, 2:16pm UTC](https://discourse.julialang.org/t/how-to-enforce-function-signature-type-on-a-struct/101211/5 "2023-07-05T14:16:21Z")

</div>

Thank you for your quick message. I know understand that julia does not param types as part of the signature.

I also read a bit and understood that having abstract types in structs is bad for performance.

I don’t really know how to take your code example further.  
How do I create a `GeneticSearchIterator` now? Do I just but `Function` in place for each `F1`,`F2`,` F3`, `F4`?

---

<div class="post-metadata">

**Author:** ![algunion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/algunion/32/51630_2.png) [@algunion](https://discourse.julialang.org/u/algunion)\
**Post date:** [July 5, 2023, 2:29pm UTC](https://discourse.julialang.org/t/how-to-enforce-function-signature-type-on-a-struct/101211/6 "2023-07-05T14:29:11Z")

</div>

Just do this:

```julia
GeneticSearchIterator(
  fitness=x -> x + 1,
  cross_over=x -> x - 1,
  (mutation!)=xs -> xs[1] = xs[1] + 1,
  mutation_probability=0.05,
  evaluation_function=() -> 0.5)

```

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/224680_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [July 5, 2023, 2:32pm UTC](https://discourse.julialang.org/t/how-to-enforce-function-signature-type-on-a-struct/101211/7 "2023-07-05T14:32:44Z")

</div>

The default constructor for a parametric struct works in exactly the same way, it will automatically infer the types of the arguments you give it so that you don’t need to specify them.

---

<div class="post-metadata">

**Author:** ![nickk2002](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nickk2002/32/202480_2.png) [@nickk2002](https://discourse.julialang.org/u/nickk2002)\
**Post date:** [July 5, 2023, 2:51pm UTC](https://discourse.julialang.org/t/how-to-enforce-function-signature-type-on-a-struct/101211/8 "2023-07-05T14:51:10Z")

</div>

> [@gdalle](#):
>
> parametric struct works in exactly the same way, it will automatically infer the types of the arguments you give it so that you don’t need to specify them.

Ok thank you very much. I did not know that.
