# Tuple or immutable struct as function argument regarding speed and optimization

**URL:** https://discourse.julialang.org/t/tuple-or-immutable-struct-as-function-argument-regarding-speed-and-optimization/23088
**Category:** Performance
**Created:** [April 12, 2019, 5:59pm UTC](https://discourse.julialang.org/t/tuple-or-immutable-struct-as-function-argument-regarding-speed-and-optimization/23088 "2019-04-12T17:59:57Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![OvidiusCicero](https://avatars.discourse-cdn.com/v4/letter/o/73ab20/32.png) [@OvidiusCicero](https://discourse.julialang.org/u/OvidiusCicero)
#### Post date: [April 12, 2019, 5:59pm UTC](https://discourse.julialang.org/t/tuple-or-immutable-struct-as-function-argument-regarding-speed-and-optimization/23088/1 "2019-04-12T17:59:57Z")

</div>

I have a function with _many_ named arguments that should not depend on global variables for performance reasons

In the following I will call the variables `a,b,c, ... ,y,z`

I want to replace them with an `immutable struct` or a a named tuple as one function argument:

Named Tuple

```julia
(a=<value>, b=<value>, c=<value>, …, y=<value>, z=<value>)

```

struct:

```julia
struct
a
b
c
…
y
z
end

```

which has the disadvantage that I still need to memorize argument order when initializing with the constructor

Are there suggestions or patterns or caveats how to handle this problem?

EDIT:  
As far as I know keyword arguments are not optimized by compiler so I want to avoid that restriction. Am I wrong with that?

EDIT 2:  
I find threads like this: [Performance of functions with keyword arguments - #3 by kristoffer.carlsson](https://discourse.julialang.org/t/performance-of-functions-with-keyword-arguments/5916/3)  
but also this younger one [Performance of typed keyword arguments](https://discourse.julialang.org/t/performance-of-typed-keyword-arguments/11579) that says they have the same speed

---

<div class="post-metadata">

### Author: ![JeffreySarnoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreysarnoff/32/1980_2.png) [@JeffreySarnoff](https://discourse.julialang.org/u/JeffreySarnoff)
#### Post date: [April 12, 2019, 6:22pm UTC](https://discourse.julialang.org/t/tuple-or-immutable-struct-as-function-argument-regarding-speed-and-optimization/23088/2 "2019-04-12T18:22:51Z")

</div>

you could use keyword arguments or this way so the order does not matter

```julia
julia> const MyNT = NamedTuple{(:a, :b, :c), T} where {T<:Tuple}
NamedTuple{(:a, :b, :c),T} where T<:Tuple

julia> MyNT( (b=3, a=1, c=2) )
(a = 1, b = 3, c = 2)

```

it also works with different types for `a`,`b`,`c`.

---

<div class="post-metadata">

### Author: ![OvidiusCicero](https://avatars.discourse-cdn.com/v4/letter/o/73ab20/32.png) [@OvidiusCicero](https://discourse.julialang.org/u/OvidiusCicero)
#### Post date: [April 12, 2019, 6:37pm UTC](https://discourse.julialang.org/t/tuple-or-immutable-struct-as-function-argument-regarding-speed-and-optimization/23088/3 "2019-04-12T18:37:31Z")

</div>

Keyword arguments are not optimized by compiler

---

<div class="post-metadata">

### Author: ![JeffreySarnoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreysarnoff/32/1980_2.png) [@JeffreySarnoff](https://discourse.julialang.org/u/JeffreySarnoff)
#### Post date: [April 12, 2019, 6:38pm UTC](https://discourse.julialang.org/t/tuple-or-immutable-struct-as-function-argument-regarding-speed-and-optimization/23088/4 "2019-04-12T18:38:35Z")

</div>

how do you feel about the NamedTuples approach?

---

<div class="post-metadata">

### Author: ![OvidiusCicero](https://avatars.discourse-cdn.com/v4/letter/o/73ab20/32.png) [@OvidiusCicero](https://discourse.julialang.org/u/OvidiusCicero)
#### Post date: [April 12, 2019, 6:40pm UTC](https://discourse.julialang.org/t/tuple-or-immutable-struct-as-function-argument-regarding-speed-and-optimization/23088/5 "2019-04-12T18:40:19Z")

</div>

Yeah that’s what I also would try. Just want to hear Pros and Cons

---

<div class="post-metadata">

### Author: ![JeffreySarnoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreysarnoff/32/1980_2.png) [@JeffreySarnoff](https://discourse.julialang.org/u/JeffreySarnoff)
#### Post date: [April 12, 2019, 6:41pm UTC](https://discourse.julialang.org/t/tuple-or-immutable-struct-as-function-argument-regarding-speed-and-optimization/23088/6 "2019-04-12T18:41:42Z")

</div>

here’s one of each 🙂  
namedtuple Pro: it does what you want  
struct Con: it does not do what you want

---

<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: [April 12, 2019, 7:43pm UTC](https://discourse.julialang.org/t/tuple-or-immutable-struct-as-function-argument-regarding-speed-and-optimization/23088/7 "2019-04-12T19:43:50Z")

</div>

> [@OvidiusCicero](#):
>
> Keyword arguments are not optimized by compiler

This is no longer true. Keyword arguments are implemented using named tuples since Julia 0.7/1.0 and are now much much faster.

For example:

```julia
julia> f1(;x = 1, y = 2) = x + y
f1 (generic function with 1 method)

julia> f2(xy::NamedTuple) = xy.x + xy.y
f2 (generic function with 1 method)

julia> struct XY{T}
         x::T
         y::T
       end

julia> f3(xy::XY) = xy.x + xy.y
f3 (generic function with 1 method)

julia> using BenchmarkTools

julia> @btime f1(x = 1, y = 2)
  1.238 ns (0 allocations: 0 bytes)
3                                                                                                                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                                                                                      
julia> @btime f2((x=1, y=2))
  0.015 ns (0 allocations: 0 bytes)                                                                                                                                                                                                                                                                                                   
3

julia> @btime f3(XY(1, 2))
  0.015 ns (0 allocations: 0 bytes)

```

All three cases are 1ns or faster. You may note that f2 and f3 appear to be much faster, but sub-1ns timings just indicate that the compiler has optimized out the entire function, since it can trivially prove that the result is unused. Setting that aside, all three options are sufficiently fast and you should pick whichever fits your use case best.

---

<div class="post-metadata">

### Author: ![OvidiusCicero](https://avatars.discourse-cdn.com/v4/letter/o/73ab20/32.png) [@OvidiusCicero](https://discourse.julialang.org/u/OvidiusCicero)
#### Post date: [April 12, 2019, 7:58pm UTC](https://discourse.julialang.org/t/tuple-or-immutable-struct-as-function-argument-regarding-speed-and-optimization/23088/8 "2019-04-12T19:58:41Z")

</div>

Thank you for clarification!

---

<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: [April 12, 2019, 8:14pm UTC](https://discourse.julialang.org/t/tuple-or-immutable-struct-as-function-argument-regarding-speed-and-optimization/23088/9 "2019-04-12T20:14:01Z")

</div>

By the way, if you want to use a struct but don’t want to have to remember the argument order, I would recommend [https://github.com/mauro3/Parameters.jl](https://github.com/mauro3/Parameters.jl) which makes it easy to define structs with more friendly constructors and default values:

```julia
julia> using Parameters

julia> @with_kw struct Foo
         x::Int = 1
         y::Float64 = 2.0
       end
Foo

julia> Foo()
Foo
  x: Int64 1
  y: Float64 2.0

julia> Foo(y = 3)
Foo                                                                                                                                                                                                                                                                                                                                   
  x: Int64 1                                                                                                                                                                                                                                                                                                                          
  y: Float64 3.0 

```

---

<div class="post-metadata">

### Author: ![tkoolen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkoolen/32/1603_2.png) [@tkoolen](https://discourse.julialang.org/u/tkoolen)
#### Post date: [April 13, 2019, 4:36am UTC](https://discourse.julialang.org/t/tuple-or-immutable-struct-as-function-argument-regarding-speed-and-optimization/23088/10 "2019-04-13T04:36:12Z")

</div>

With Julia 1.1, you probably don’t even need Parameters.jl and could just use `Base.@kwdef` instead of `Parameters.@with_kw`.

---

<div class="post-metadata">

### Author: ![Wen-Wei\_Tseng](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wen-wei_tseng/32/28839_2.png) [@Wen-Wei\_Tseng](https://discourse.julialang.org/u/Wen-Wei_Tseng)
#### Post date: [May 29, 2020, 3:44am UTC](https://discourse.julialang.org/t/tuple-or-immutable-struct-as-function-argument-regarding-speed-and-optimization/23088/11 "2020-05-29T03:44:08Z")

</div>

And the author (mauro3) of Parameters stated that `Parameter.jl` will align with `Base.@kwdef` with some API breakage. [Release 1.0? · Issue #121 · mauro3/Parameters.jl · GitHub](https://github.com/mauro3/Parameters.jl/issues/121).  
There is another package of mauro3, [Unpack.jl](https://github.com/mauro3/UnPack.jl), doing `@unpack a,b,c = p` instead of `a, b, c = p.a, p.b, p.c` for dicts / structs / namedtuples / labelled arrays, which is handy IMHO.
