# Union of types in arguments of function

**URL:** https://discourse.julialang.org/t/union-of-types-in-arguments-of-function/6022
**Category:** General Usage
**Created:** [September 21, 2017, 1:15pm UTC](https://discourse.julialang.org/t/union-of-types-in-arguments-of-function/6022 "2017-09-21T13:15:05Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![plapplop](https://avatars.discourse-cdn.com/v4/letter/p/bbce88/32.png) [@plapplop](https://discourse.julialang.org/u/plapplop)
#### Post date: [September 21, 2017, 1:15pm UTC](https://discourse.julialang.org/t/union-of-types-in-arguments-of-function/6022/1 "2017-09-21T13:15:05Z")

</div>

I had a code working in Julia 0.5 that was designed a bit specially for historical reasons:

```julia
function f{P,Q}(x::Union{P,Q}) return x end
type P a::Int end
type Q b::Float64 end
p = P(1)
q = Q(2.0)
f(p)
f(q)

```

I want this function f to work for two different types, but I don’t want to write two times the same code.  
The types for which I define f are necessarily defined after it.  
This does not work in 0.6 anymore, there’s an error raised:

```julia
ERROR: LoadError: MethodError: no method matching f(::P)
Closest candidates are:
  f(::Union{P, Q}) where {P, Q} at ~/Code/test-julia/union-types.jl:2
Stacktrace:
 [1] include_from_node1(::String) at ./loading.jl:569
 [2] include(::String) at ./sysimg.jl:14
 [3] process_options(::Base.JLOptions) at ./client.jl:305
 [4] _start() at ./client.jl:371
while loading ~/Code/test-julia/union-types.jl, in expression starting on line 7

```

So my questions are:

- Is there a true gain in performance if I specify the type of x or is it OK if I don’t?
- Why doesn’t this syntax work anymore in 0.6?
- What would be the optimal solution for what I want to do?

Many thanks!

---

<div class="post-metadata">

### Author: ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)
#### Post date: [September 21, 2017, 1:38pm UTC](https://discourse.julialang.org/t/union-of-types-in-arguments-of-function/6022/2 "2017-09-21T13:38:05Z")

</div>

Note that your function definition is probably not what you intend it to be, and is equivalent to `f(x::Any) = x`, in Julia 0.5 (as far as I know, but there might be subtle differences). This becomes clearer if you rewrite it in the following 100% equivalent way:

```julia
function f{T1,T2}(x::Union{T1,T2}) return x end
type P a::Int end
type Q b::Float64 end
p = P(1)
q = Q(2.0)
f(p)
f(q)

```

In Julia 0.6, due to the type-system re-vamp, the method behaves differently, as it requires both type variables `T1,T2` to be matched. However, that has been relaxed again in 0.7 and your function works again as before.

But still, I’m pretty sure it does not what it is intended to do…

---

<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: [September 21, 2017, 7:26pm UTC](https://discourse.julialang.org/t/union-of-types-in-arguments-of-function/6022/4 "2017-09-21T19:26:35Z")

</div>

No, there is absolutely no performance difference if you specify the type of `x` or not. And, based on what @mauro3 suggested, you can fix this by just removing the `{P,Q}` entirely:

```julia
type P a::Int end
type Q b::Float64 end
function f(x::Union{P, Q}) return x end
p = P(1)
q = Q(2.0)
f(p)
f(q)

```

---

<div class="post-metadata">

### Author: ![plapplop](https://avatars.discourse-cdn.com/v4/letter/p/bbce88/32.png) [@plapplop](https://discourse.julialang.org/u/plapplop)
#### Post date: [September 22, 2017, 2:19pm UTC](https://discourse.julialang.org/t/union-of-types-in-arguments-of-function/6022/5 "2017-09-22T14:19:50Z")

</div>

@mauro3 It does probably not what it is intended to indeed, it’s been a long time since I wrote this code but just to be clear about what I thought:

- I thought that in the general case it could help the compiler to specify the types of the arguments in a function, is this true?

- I thought that when the types are undefined, defining a function the way I did would maybe tell the compiler: ok these types do not exist yet, but they will in the future, when you encounter them, optimize the functions based on the content of these types. I thought very highly of the compiler back then 🙂

@rdeits What you propose is slightly different than what I need because you defined types P and Q before the function, which I can’t do.

Thanks to you both for the replies!

---

<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: [September 22, 2017, 2:28pm UTC](https://discourse.julialang.org/t/union-of-types-in-arguments-of-function/6022/6 "2017-09-22T14:28:18Z")

</div>

Ah, yeah, if the types aren’t defined before the function, then you can’t do this. But, to be clear, there is absolutely no performance difference one way or the other. The types that show up in the declaration just determine whether a particular method gets called. The “optimize the functions based on the content of these types” is _always_ done for every input to every function, regardless of whether you’ve specified anything about the inputs or not.

---

<div class="post-metadata">

### Author: ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)
#### Post date: [September 22, 2017, 3:29pm UTC](https://discourse.julialang.org/t/union-of-types-in-arguments-of-function/6022/7 "2017-09-22T15:29:19Z")

</div>

Yep, type annotation for function arguments is only needed for dispatch (and for documentation) but not for performance as the JIT will compile a new “method” for each input.

---

<div class="post-metadata">

### Author: ![plapplop](https://avatars.discourse-cdn.com/v4/letter/p/bbce88/32.png) [@plapplop](https://discourse.julialang.org/u/plapplop)
#### Post date: [September 22, 2017, 3:35pm UTC](https://discourse.julialang.org/t/union-of-types-in-arguments-of-function/6022/8 "2017-09-22T15:35:06Z")

</div>

Ok, thank you very much to both of you, I understand better now, and this will greatly simplify my code…!

---

<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: [September 22, 2017, 8:07pm UTC](https://discourse.julialang.org/t/union-of-types-in-arguments-of-function/6022/9 "2017-09-22T20:07:31Z")

</div>

The way your question is phrased, plus this statement

> [@plapplop](#):
>
> I thought that when the types are undefined, defining a function the way I did would maybe tell the compiler: ok these types do not exist yet, but they will in the future, when you encounter them, optimize the functions based on the content of these types. I thought very highly of the compiler back then 🙂

makes me suspect that you are laboring under some misunderstanding about types and type variables.

```julia
foo(x::Union{P, Q})

```

and

```julia
foo{P, Q}(x::Union{P, Q})

```

mean _very_ different things. The first means: call this method if `x` is either of type `P` or type `Q`, where `P` and `Q` are real, defined types.

In the second one, `P` and `Q` are type _variables_, which means they have _nothing_ to do with the types `P` or `Q`, but can take on the value of any type. The definition is basically (except for some technicalities) the same as `foo(x::Union{Any, Any})` which again is the same as `foo(x::Any)`.

A simpler example is that `bar(x::Int)` will only match `Int`s, but `bar{Int}(x::Int)` will match any input type, because here `Int` is a type variable:

```julia
julia> bar{Int}(x::Int) = "hello, $x"
bar (generic function with 1 method)

julia> bar(98)
"hello, 98"

julia> bar("joe")
"hello, joe"

```

Another analogy could be if you defined `foo(x) = x^2` and then outside that scope you defined a variable binding `x = 10`. The `x` inside `foo` has nothing to do with the variable `x` that has the value 10, it’s just a coincidence of naming.

---

<div class="post-metadata">

### Author: ![plapplop](https://avatars.discourse-cdn.com/v4/letter/p/bbce88/32.png) [@plapplop](https://discourse.julialang.org/u/plapplop)
#### Post date: [September 22, 2017, 8:30pm UTC](https://discourse.julialang.org/t/union-of-types-in-arguments-of-function/6022/10 "2017-09-22T20:30:53Z")

</div>

Hi DNF, thanks for the great additional information. Everything’s clearer now!
