# Functions with many arguments

**URL:** <https://discourse.julialang.org/t/functions-with-many-arguments/20974>\
**Category:** General Usage\
**Tags:** argument, functions\
**Created:** [February 19, 2019, 1:05pm UTC](https://discourse.julialang.org/t/functions-with-many-arguments/20974 "2019-02-19T13:05:59Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![milankl](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milankl/32/4198_2.png) [@milankl](https://discourse.julialang.org/u/milankl)\
**Post date:** [February 19, 2019, 1:05pm UTC](https://discourse.julialang.org/t/functions-with-many-arguments/20974/1 "2019-02-19T13:05:59Z")

</div>

I’m currently running into a situation where my functions need to operate on many potentially huge matrices of slightly different sizes. I preallocate all memory first, such that all functions take elements from some of the input arguments, do a computation and store it in one of the others, e.g.

```julia
function rhs!(U,V,A,B,C,D,E,F,G)
    func1!(U,V,A,B)
    func2!(U,V,C,D)
    func3!(U,V,D,E)
    func4!(U,V,F,G)
end

```

If I have more like 30+ arguments I can’t even be bothered to write ::AbstractMatrix for readability. Inside rhs! many of the matrices are read&write, some are read-only (U,V in this example). In almost all cases I am also totally fine if the variable names are the same inside the function and in the outer scope:

```julia
U,V = preallocate1(...)
A,B,C,D,E,F,G,H = preallocate2(...)

for i in 1:n
    ...
    rhs!(U,V,A,B,C,D,E,F,G,H)
    ...
end

```

Is there a recommended way how to maintain readability whilst declaring everything correctly and avoiding zipping into tuples and unpacking the variables? I guess, technically I could set A,B,C,… as constants, and not pass them on as an argument but then everytime I store some new entries in them I would get a redefining constant warning.

---

<div class="post-metadata">

**Author:** ![LaurentPlagne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/laurentplagne/32/10103_2.png) [@LaurentPlagne](https://discourse.julialang.org/u/LaurentPlagne)\
**Post date:** [February 19, 2019, 1:15pm UTC](https://discourse.julialang.org/t/functions-with-many-arguments/20974/2 "2019-02-19T13:15:16Z")

</div>

Sorry in advance if I am totally out of scope.  
If some of your arguments are semantically related it may be a good idea to group them inside a struct (immutable). In your example, is it possible that some matrix arguments happen to be blocks of a larger block matrix ?

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [February 19, 2019, 1:18pm UTC](https://discourse.julialang.org/t/functions-with-many-arguments/20974/3 "2019-02-19T13:18:44Z")

</div>

> [@milankl](#):
>
> I have more like 30+ arguments

I would say that more than 3 positional arguments are likely to be code smell, and more than 5 definitely is a very bad idea.

As @LaurentPlagne suggested, wrap them in something: a `struct`, a `NamedTuple`, or similar. `preallocate1` should return this object instead, etc.

---

<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 19, 2019, 1:22pm UTC](https://discourse.julialang.org/t/functions-with-many-arguments/20974/4 "2019-02-19T13:22:08Z")

</div>

> [@milankl](#):
>
> I guess, technically I could set A,B,C,… as constants, and not pass them on as an argument but then everytime I store some new entries in them I would get a redefining constant warning.

I wouldn’t recommend that, for exactly the reason you noted and also because it obscures what your function is doing. As others have stated, there is almost certain to be a better way to organize your arguments than a flat collection of dozens of matrices. Putting those matrices into a struct is an improvement, but I would suggest that you consider whether there is even more structure to your data than that. Can your function be broken up into pieces that operate on just some of those matrices? Then perhaps those matrices form a logical unit. Can you give that group a name? Then perhaps that group should be its own struct inside your outer struct.

---

<div class="post-metadata">

**Author:** ![milankl](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milankl/32/4198_2.png) [@milankl](https://discourse.julialang.org/u/milankl)\
**Post date:** [February 19, 2019, 1:51pm UTC](https://discourse.julialang.org/t/functions-with-many-arguments/20974/5 "2019-02-19T13:51:18Z")

</div>

I see so what’s recommend is something like that

```julia
mutable struct Group1
    A::AbstractMatrix
    B::AbstractMatrix
    C::AbstractMatrix
end

function rhs!(Gr1,Gr2,Gr3)
    func1!(Gr1.A,Gr2.B)
    func2!(Gr1.D,Gr2.E)
    ...
end

# preallocation
Gr1 = Group1(zeros(30,30),zeros(32,30),zeros(30,32))

for i in 1:n  
    ...
    rhs!(Gr1,Gr2,Gr3)
    ...
end

```

which would only require to rewrite some of the arguments inside the rhs! function with the dot notation Gr1.A etc. I guess I could live with that!

---

<div class="post-metadata">

**Author:** ![LaurentPlagne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/laurentplagne/32/10103_2.png) [@LaurentPlagne](https://discourse.julialang.org/u/LaurentPlagne)\
**Post date:** [February 19, 2019, 1:58pm UTC](https://discourse.julialang.org/t/functions-with-many-arguments/20974/6 "2019-02-19T13:58:33Z")

</div>

That is what I had in mind. It makes sense if Group1 really means something and have a significant name.  
In addition you may define a “Ctor”/function with the same name to build your struct.

In addition I would not recommend to store abstract types in struct. Either you now the concrete type or you can use parametric types. Abstract types are OK with functions but cause performance problem inside structs.

---

<div class="post-metadata">

**Author:** ![ericphanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericphanson/32/215186_2.png) [@ericphanson](https://discourse.julialang.org/u/ericphanson)\
**Post date:** [February 19, 2019, 2:00pm UTC](https://discourse.julialang.org/t/functions-with-many-arguments/20974/7 "2019-02-19T14:00:25Z")

</div>

[Parameters.jl](https://github.com/mauro3/Parameters.jl) is very useful for that, because inside `rhs!(Gr1,Gr2,Gr3)` you could just put

```julia
@unpack U,V,A,B = Gr1
@unpack C,D,E,F = Gr2
@unpack G,H = Gr3

```

or however it works, and then you don’t have to change the rest of your implementation of `rhs!(U,V,A,B,C,D,E,F,G,H)` when converting it to use structs.

---

<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 19, 2019, 2:07pm UTC](https://discourse.julialang.org/t/functions-with-many-arguments/20974/8 "2019-02-19T14:07:20Z")

</div>

Just one more suggestion: when writing a struct definition, it is important to use concrete types for the fields of the struct (see [Performance Tips · The Julia Language](https://docs.julialang.org/en/v1/manual/performance-tips/index.html#Avoid-fields-with-abstract-type-1) ). For example,

```julia
struct Foo
  x::Matrix{Float64}
end

```

instead of:

```julia
struct Foo
   x::AbstractMatrix
end

```

Note that if you still want to handle any kind of scalar, you can use a parametric type:

```julia
struct Foo{T}
  x::Matrix{T}
end

```

and if you want to handle any kind of matrix without any performance penalty, you can put the entire matrix type into the parameters of your struct:

```julia
struct Foo{M <: AbstractMatrix}
  x::M 
end

```
