# Passing arguments to julia functions

**URL:** <https://discourse.julialang.org/t/passing-arguments-to-julia-functions/64335>\
**Category:** New to Julia\
**Tags:** argument, functions, options\
**Created:** [July 9, 2021, 9:26am UTC](https://discourse.julialang.org/t/passing-arguments-to-julia-functions/64335 "2021-07-09T09:26:35Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![BambOoxX](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bambooxx/32/22179_2.png) [@BambOoxX](https://discourse.julialang.org/u/BambOoxX)\
**Post date:** [July 9, 2021, 9:26am UTC](https://discourse.julialang.org/t/passing-arguments-to-julia-functions/64335/1 "2021-07-09T09:26:36Z")

</div>

Former Matlab user here, still discovering new things about type stability and multiple dispatch…

Currently working on a private package involving mostly linear algebra, I tried to follow the philosophy of julia’s multiple dispatch whenever I could, maybe too much even.

In my package I have a function `fun` that has different methods based on some symbol parameter set `p1`, `p2`, `...`, but always returns the same type. I am not yet used to having types as parameters to perform the multiple dispatch. So my current implementation involves multiple methods defined as

```julia
function fun(<common_args...>, ::Val{:p1}`)::ret_type
    <some code>
end

function fun(<common_args...>, ::Val{:p2}`)::ret_type
    <some other code>
end

```

And the function calls are done with e.g. : `fun(<common_args...>,Val(:p1))`

I do not know anymore where I got this _trick_ from, but it works for sure.  
However, it seems this can lead to a high stress on the compiler (this comment is based on a discussion on slack)  
Also, some `@code_warntype` analysis shows that this doesn’t really ensure type stability, even when explicitly specifying the return type for each method in `fun`.

In some other way, yet related to the current discussion I tried to see what was done in some base julia code, to see if I could get a _typical_ julia implementation. For instance, take the `Hermitian` from `Base`.

`Hermitian` takes a second argument `uplo` which is a symbol (I figured symbols are something important in julia but I can quite fathom how), this comforted me in my practice to use symbols as arguments.

However the definition of `Hermitian` is

```julia
function Hermitian(A::AbstractMatrix, uplo::Symbol=:U)
    n = checksquare(A)
    return hermitian_type(typeof(A))(A, char_uplo(uplo))
end

```

so no check in the value of `uplo` is done at that time, just on its type, so there is no multiple dispatch involved here it seems. Then one can see the `char_uplo` call… which is actually a check on the value of `uplo` ! This check is defined as

```julia
function char_uplo(uplo::Symbol)
    if uplo === :U
        return 'U'
    elseif uplo === :L
        return 'L'
    else
        throw_uplo()
    end
end

```

The most surprising part of this to me, is that one actually converts the symbol parameter as a char parameter, what is the reasoning behind this ?

Overall my question is: What is the correct way in julia to have a function with multiple implementations differing according to parameter values :

- Is it necessarily through _true_ multiple dispatch where one would define types as parameters e.g.  
`:p1` would be replaced by a `p1type` and `fun` would be defined as

```julia
function fun(<common_args...>, ::p1type)::ret_type
    <some code>
end
function fun(<common_args...>, ::p2type)::ret_type
    <some other code>
end

```

- Is it through type specification with e.g. `p::Symbol`, then applying the `char_uplo` strategy ?
- Some other way ?

This has probably been discussed somewhere, but I would really like a feedback on this. As often there will probably be no unique solution, but I just need one… 🙂

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [July 9, 2021, 7:20pm UTC](https://discourse.julialang.org/t/passing-arguments-to-julia-functions/64335/2 "2021-07-09T19:20:18Z")

</div>

I think that a bit more context is needed to give a truly useful answer.

If the property that determines the version of `fun` to be called can be determined at compile time, a Trait would be a possible solution.

If not, you may not be able to do better than dispatch via garden variety `if ... else`.  
On the other hand, if you want the solution to be extensible to new types, Traits may still be the best solution (you don’t get static dispatch, but you do get extendability).

---

<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:** [July 9, 2021, 8:11pm UTC](https://discourse.julialang.org/t/passing-arguments-to-julia-functions/64335/3 "2021-07-09T20:11:07Z")

</div>

> [@BambOoxX](#):
>
> I figured symbols are something important in julia but I can quite fathom how

Symbols are basically just strings, but they have some nice features:

- Internally, Julia represents the names of things in your code as `Symbol`s, so they show up a lot in metaprogramming (code that generates code)
- They are generally more efficient to compare for equality than strings, so they’re very useful when you want a lightweight way to differentiate a few different named things (and don’t want to use types for that purpose)

But the set of things you can do with a Symbol is pretty similar to the set of things you can do with a string (you can easily convert one to the other, at the cost of some copying of data). We generally use Symbols when dealing with things which appear directly in your code, while we use Strings when dealing with input from files or users or network streams.

> [@BambOoxX](#):
>
> The most surprising part of this to me, is that one actually converts the symbol parameter as a char parameter, what is the reasoning behind this ?

I suspect this is because if you were to dig deeper you would find a call to some existing BLAS function or some Julia code with the same interface. Lots of BLAS routines use characters like this to indicate what kind of operation should be performed. Pure Julia code probably wouldn’t do this (a Symbol might be more appropriate), but we’re talking about Fortran libraries whose interfaces haven’t changed in decades.

> [@BambOoxX](#):
>
> Overall my question is: What is the correct way in julia to have a function with multiple implementations differing according to parameter values :

This will depend a lot on your case. There’s nothing at all wrong with just taking a `Symbol` or boolean flag and writing an `if` statement. That will produce very fast code and can be the easiest thing to do in some cases.

An approach like `fun(... ::pytype)` and `fun(... ::p2type)` is also very common. The biggest advantage of that design is that it’s very easy for a future user (or you) to then go on and implement `fun(... ::p3type)` without needing to modify any existing code. It /can/ also give better performance, but this is likely only going to matter if `fun` is in the innermost loop of your code.

I wouldn’t worry about copying the `char_uplo` pattern unless you also need to interface with some older code that expects a literal `Char` somewhere.

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [July 9, 2021, 8:11pm UTC](https://discourse.julialang.org/t/passing-arguments-to-julia-functions/64335/4 "2021-07-09T20:11:23Z")

</div>

`if ... else` is probably the way to go. The one exception is if the return type depends on on the value as well.

Right now I would focus on the source of the type instability. The return type assertion will not necessarily solve the issue.

---

<div class="post-metadata">

**Author:** ![BambOoxX](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bambooxx/32/22179_2.png) [@BambOoxX](https://discourse.julialang.org/u/BambOoxX)\
**Post date:** [July 11, 2021, 5:25pm UTC](https://discourse.julialang.org/t/passing-arguments-to-julia-functions/64335/5 "2021-07-11T17:25:33Z")

</div>

Thanks for the clarification about the whole char conversion thing. That surely makes sense when interfacing wild external libraries.

In my case (and for the moment of course), this kind of call is at quite high-level, so this should not be a performance issue indeed. I was just wondering what would be the more appropriate way to do this in julia beyond the obvious `if ... else` statement. This is probably because I discovered multiple dispatch with julia, and now I’m trying to force it a bit… it really fells like a fancy and implicit `if ... else` to me but I’m sure it’s much more than that.

---

<div class="post-metadata">

**Author:** ![BambOoxX](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bambooxx/32/22179_2.png) [@BambOoxX](https://discourse.julialang.org/u/BambOoxX)\
**Post date:** [July 11, 2021, 5:27pm UTC](https://discourse.julialang.org/t/passing-arguments-to-julia-functions/64335/6 "2021-07-11T17:27:54Z")

</div>

The parameter is given a value at runtime, basically it is some option that the user defines for some algorithm…

Can you clarify a bit the role of traits in this context ?

---

<div class="post-metadata">

**Author:** ![genkuroki](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/genkuroki/32/18030_2.png) [@genkuroki](https://discourse.julialang.org/u/genkuroki)\
**Post date:** [July 11, 2021, 6:11pm UTC](https://discourse.julialang.org/t/passing-arguments-to-julia-functions/64335/7 "2021-07-11T18:11:05Z")

</div>

If you can work in [the problem-algorithm-solver pattern](https://discourse.julialang.org/t/function-depending-on-the-global-variable-inside-module/64322/10), I think it is safe to follow that. In that pattern, different algorithms are represented by different types, and the solver function `solve` is dispatched by different algorithm types.

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [July 13, 2021, 7:05pm UTC](https://discourse.julialang.org/t/passing-arguments-to-julia-functions/64335/8 "2021-07-13T19:05:59Z")

</div>

I see two potential benefits of Traits of `if ... else`:

1. Performance: if you can achieve static dispatch (the value of the option can be inferred at compile time), this can be much faster than `if ... else`.
2. Extendability: if the number of options may expand in the future, this is possible with a Trait (without changing the original code), but not (obviously) with the `if ... else`.

It sounds like neither concern applies in your case, in which case I don’t see anything wrong with `if ... else`.

---

<div class="post-metadata">

**Author:** ![bernhard](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bernhard/32/2619_2.png) [@bernhard](https://discourse.julialang.org/u/bernhard)\
**Post date:** [July 13, 2021, 7:26pm UTC](https://discourse.julialang.org/t/passing-arguments-to-julia-functions/64335/9 "2021-07-13T19:26:35Z")

</div>

I did not know that dispatch is faster than if else. Can you give a reference for this please?

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [July 13, 2021, 8:08pm UTC](https://discourse.julialang.org/t/passing-arguments-to-julia-functions/64335/10 "2021-07-13T20:08:33Z")

</div>

Static dispatch can be faster if the to-be-dispatched-to function is inlined. No jump/branch is faster than any branch, most of the time (branch predictors can get lucky).

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [July 13, 2021, 8:11pm UTC](https://discourse.julialang.org/t/passing-arguments-to-julia-functions/64335/11 "2021-07-13T20:11:41Z")

</div>

I should note that type dependent if-else constructs can often be eliminated by the compiler, so it’s not always clear cut which is going to be faster if the branch/dispatch is decided by types alone.

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [July 13, 2021, 10:38pm UTC](https://discourse.julialang.org/t/passing-arguments-to-julia-functions/64335/12 "2021-07-13T22:38:31Z")

</div>

It’s a good question. The fact that static dispatch is fast and dynamic dispatch is slow seems implied in many places (and intuitive) (setting aside compiler optimizations where seemingly dynamic dispatch is converted into static dispatch, such as eliding dead branches). But I don’t have a reference.

---

<div class="post-metadata">

**Author:** ![genkuroki](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/genkuroki/32/18030_2.png) [@genkuroki](https://discourse.julialang.org/u/genkuroki)\
**Post date:** [July 14, 2021, 12:08am UTC](https://discourse.julialang.org/t/passing-arguments-to-julia-functions/64335/13 "2021-07-14T00:08:28Z")

</div>

Optimization by specialization to argument types comes with the tradeoff of increased compilation time. An extreme case of this is shown in the following example.

```julia
f(x) = x^2 + 3x + 2
g(::Val{x}) where x = f(x)
f(10^6), g(Val(10^6))

```

```julia
(1000003000002, 1000003000002)

```

```julia
using BenchmarkTools
@btime f(10^6)
@btime g($(Val(10^6)));

```

```julia
  3.500 ns (0 allocations: 0 bytes)
  0.001 ns (0 allocations: 0 bytes)

```

`g(Val(10^6))` is ultra fast because it is specialized to the argument type `Val{10^6}` and compiled to `return 1000003000002`.

```julia
@code_typed debuginfo=:none g(Val(10^6))

```

```julia
CodeInfo(
1 ─ return 1000003000002
) => Int64

```

However, `g(Val(k))` is compiled separately for each different `k`. So if you run `g(Val(k))` for a large number of different `k`’s, it will perform a large number of compilations and will be very slow. (After compilation, though, it will be explosively fast.)

```julia
F(n) = [f(k) for k in 1:n]
G(n) = [g(Val(k)) for k in 1:n]

@time F(10^4)
@time G(10^4);

```

```julia
  0.000010 seconds (2 allocations: 78.203 KiB)
  5.160295 seconds (55.43 M allocations: 3.894 GiB, 14.56% gc time, 95.65% compilation time)

```

The first execution of `G(10^4)` is very slow.

Thus, it is not reasonable to try to optimize by specialization to the argument types by different large numbers of `Val{k}` types.

On the other hand, the native code specialized to argument types is very fast, so if compilation time is not an issue, optimization by specialization to argument types should be done aggressively.

In short, it is a matter of trade-off.

---

<div class="post-metadata">

**Author:** ![genkuroki](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/genkuroki/32/18030_2.png) [@genkuroki](https://discourse.julialang.org/u/genkuroki)\
**Post date:** [July 14, 2021, 12:35am UTC](https://discourse.julialang.org/t/passing-arguments-to-julia-functions/64335/14 "2021-07-14T00:35:33Z")

</div>

> [@BambOoxX](#):
>
> Is it through type specification with e.g. `p::Symbol` , then applying the `char_uplo` strategy ?

No. Don’t apply “the `char_uplo` strategy”.

The reason why Hermitian type has the field `uplo` of type Char instead of Symbol is to conform to the LAPACK library specification.

See, for example, [https://github.com/JuliaLang/julia/blob/44d484222005580432433b7889c4a56d25c0ea67/stdlib/LinearAlgebra/src/lapack.jl#L5112-L5124](https://github.com/JuliaLang/julia/blob/44d484222005580432433b7889c4a56d25c0ea67/stdlib/LinearAlgebra/src/lapack.jl#L5112-L5124)

Because of these special circumstances, please forget about `char_uplo` in ordinary Julia programming.

It’s not so bad if you simply follow the problem-algorithm-solver pattern.

---

<div class="post-metadata">

**Author:** ![bernhard](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bernhard/32/2619_2.png) [@bernhard](https://discourse.julialang.org/u/bernhard)\
**Post date:** [July 14, 2021, 6:58am UTC](https://discourse.julialang.org/t/passing-arguments-to-julia-functions/64335/15 "2021-07-14T06:58:53Z")

</div>

But you have not compared this to an if-then-else approach so far.  
Wouldn’t this be similarly fast?

I gave this a try, but I think the compiler outsmarted me somehow…

```julia

function if_vs_dispatch(x)
    if x == 10_000_000
        return 1000003000002
    else 
        return f(x)
    end
end

julia> @btime if_vs_dispatch(10_000_00)
  0.001 ns (0 allocations: 0 bytes)
1000003000002

julia> @btime if_vs_dispatch(10_000_000)
  0.001 ns (0 allocations: 0 bytes)
1000003000002

julia> @btime if_vs_dispatch(932)
  0.001 ns (0 allocations: 0 bytes)
871422

julia> @btime if_vs_dispatch(10_000_000)
  0.001 ns (0 allocations: 0 bytes)
1000003000002

julia> @btime if_vs_dispatch(9112)
  0.001 ns (0 allocations: 0 bytes)
83055882

julia> @btime g($(Val(10^6)));
  0.001 ns (0 allocations: 0 bytes)

julia> @btime if_vs_dispatch(123)
  0.001 ns (0 allocations: 0 bytes)
15500

```

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [July 14, 2021, 7:10am UTC](https://discourse.julialang.org/t/passing-arguments-to-julia-functions/64335/16 "2021-07-14T07:10:21Z")

</div>

Sub-nanosecond timings are always impossible for real computation, even just an addition takes 2-3ns. Check with `@code_native` or `@code_llvm` how much has been optimized away - in this case, I suspect constant propagation is what eliminated all computation.

---

<div class="post-metadata">

**Author:** ![genkuroki](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/genkuroki/32/18030_2.png) [@genkuroki](https://discourse.julialang.org/u/genkuroki)\
**Post date:** [July 14, 2021, 8:17am UTC](https://discourse.julialang.org/t/passing-arguments-to-julia-functions/64335/17 "2021-07-14T08:17:15Z")

</div>

Yes. I have not mentioned anything about “an if-then-else approach”.
