# Unions vs adding methods

**URL:** <https://discourse.julialang.org/t/unions-vs-adding-methods/2298>\
**Category:** General Usage\
**Tags:** question\
**Created:** [February 25, 2017, 1:29pm UTC](https://discourse.julialang.org/t/unions-vs-adding-methods/2298 "2017-02-25T13:29:21Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![barche](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barche/32/79_2.png) [@barche](https://discourse.julialang.org/u/barche)\
**Post date:** [February 25, 2017, 1:29pm UTC](https://discourse.julialang.org/t/unions-vs-adding-methods/2298/1 "2017-02-25T13:29:21Z")

</div>

I just read up on Unions, and I get the impression that approach A and B below would be exactly equivalent:

```julia
int32_only_eater(i::Int32) = println(i)

# Approach A
eatint(i::Int32) = int32_only_eater(i)
eatint(i::Int64) = int32_only_eater(convert(Int32,i))
eatint(i::Float64) = int32_only_eater(convert(Int32,i))

# Approach B
typealias IntUnion Union{Int32,Int64,Float64}
eatint2(i::IntUnion) = int32_only_eater(convert(Int32,i))

```

Is that correct? If so, I have been making my life needlessly complicated by using approach A.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [February 25, 2017, 1:47pm UTC](https://discourse.julialang.org/t/unions-vs-adding-methods/2298/2 "2017-02-25T13:47:34Z")

</div>

Not (currently) for ambiguity resolution purpose.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [February 25, 2017, 1:52pm UTC](https://discourse.julialang.org/t/unions-vs-adding-methods/2298/3 "2017-02-25T13:52:37Z")

</div>

And for possible change of ambituity detection in the future, it’s a matter of whether `f(::Union{A,B},::A)` and `f(::A,::Union{A,B})` should be an method redefinition warning or an ambiguity.

---

<div class="post-metadata">

**Author:** ![greg\_plowman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/greg_plowman/32/8100_2.png) [@greg\_plowman](https://discourse.julialang.org/u/greg_plowman)\
**Post date:** [February 25, 2017, 3:28pm UTC](https://discourse.julialang.org/t/unions-vs-adding-methods/2298/4 "2017-02-25T15:28:31Z")

</div>

> [@yuyichao](#):
>
> f(::Union{A,B},::A) and f(::A,::Union{A,B})

I understand the ambiguity in this example, but in cases where there is no ambiguity isn’t it the same as writing out all permutations of arguments? (this seems strangely circular, but I hope you know what I mean)

In particular, for the 1-argument example in the original post, aren’t the two approaches the same?

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [February 25, 2017, 3:52pm UTC](https://discourse.julialang.org/t/unions-vs-adding-methods/2298/5 "2017-02-25T15:52:50Z")

</div>

> [@greg\_plowman](#):
>
> In particular, for the 1-argument example in the original post, aren’t the two approaches the same?

That’s what I said. They are not the same for the purpose of ambiguity detection and therefore dispatch. You can get ambiguity with only a single argument without any problem.

```julia
julia> f(::Union{Int,Float32}) = 1
f (generic function with 1 method)

julia> f(::Union{Int,Float64}) = 2
f (generic function with 2 methods)

julia> f(1)
ERROR: MethodError: f(::Int64) is ambiguous. Candidates:
  f(::Union{Float64, Int64}) in Main at REPL[2]:1
  f(::Union{Float32, Int64}) in Main at REPL[1]:1

```

---

<div class="post-metadata">

**Author:** ![barche](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barche/32/79_2.png) [@barche](https://discourse.julialang.org/u/barche)\
**Post date:** [February 25, 2017, 3:52pm UTC](https://discourse.julialang.org/t/unions-vs-adding-methods/2298/6 "2017-02-25T15:52:54Z")

</div>

> [@greg\_plowman](#):
>
> In particular, for the 1-argument example in the original post, aren’t the two approaches the same?

A quick check with `@code_native` seems to indicate they generate the same code at least. I think in my application the ambiguities are not really an issue, it’s mostly in the context of CxxWrap to make it easier to pass things like unsigned integers to C++ (i.e. without asking users to put UInt() around arguments) and also to allow passing an object and its smart pointer to the same function. Currently I have code that indeed generates all permutations for all requested overloads, so I was hoping to simplify this using Unions.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [February 25, 2017, 3:55pm UTC](https://discourse.julialang.org/t/unions-vs-adding-methods/2298/7 "2017-02-25T15:55:07Z")

</div>

Well, the signature you specify only affect dispatch and only in very rare cases affect code generation (`Function` and `Type`) so in that sense, nothing you put there affect specialization and `Union` is totally irrelevant here.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [February 25, 2017, 3:56pm UTC](https://discourse.julialang.org/t/unions-vs-adding-methods/2298/8 "2017-02-25T15:56:25Z")

</div>

And of course they affect dispatch more than just ambiguity detection because it can affect `invoke` too for the same reason.

```julia
julia> invoke(f, Tuple{Union{Int,Float32}}, 1)
1

```

---

<div class="post-metadata">

**Author:** ![greg\_plowman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/greg_plowman/32/8100_2.png) [@greg\_plowman](https://discourse.julialang.org/u/greg_plowman)\
**Post date:** [February 25, 2017, 4:01pm UTC](https://discourse.julialang.org/t/unions-vs-adding-methods/2298/9 "2017-02-25T16:01:30Z")

</div>

Yes, I shouldn’t have said “1-argument”, but rather the circular-sounding “when there are no ambiguities”.  
I was interpreting the original question as whether these are identical:

```julia
f(::Union{Int,Float32}) = 1

```

and

```julia
f(::Int) = 1
f(::Float32) = 1

```

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [February 25, 2017, 4:22pm UTC](https://discourse.julialang.org/t/unions-vs-adding-methods/2298/10 "2017-02-25T16:22:55Z")

</div>

As I said

- For performance it doesn’t matter whatever you put in the signature. Whether it is `Union` or not.
- For dispatch, it matters for certain cases and doesn’t matter for other cases.  
If your question is if it doesn’t matter for the cases it doesn’t matter than the answer is obviously yes. My two comments above are just pointing out the cases that I can think of where it does matter.

---

<div class="post-metadata">

**Author:** ![greg\_plowman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/greg_plowman/32/8100_2.png) [@greg\_plowman](https://discourse.julialang.org/u/greg_plowman)\
**Post date:** [February 25, 2017, 4:43pm UTC](https://discourse.julialang.org/t/unions-vs-adding-methods/2298/11 "2017-02-25T16:43:04Z")

</div>

OK, I think I finally get it. Thank you.

As you said, “method redefinition warning or an ambiguity”.

The following was instructive for me:

```julia
julia v0.5.0> f(::Union{Int,Float32}) = 1
f (generic function with 1 method)

julia v0.5.0> f(::Union{Int,Float64}) = 2
f (generic function with 2 methods)

julia v0.5.0> f(1)
ERROR: MethodError: f(::Int64) is ambiguous. Candidates:
  f(::Union{Float64,Int64}) at REPL[2]:1
  f(::Union{Float32,Int64}) at REPL[1]:1

```

Separate definitions:

```julia
julia v0.5.0> f(::Int) = 1
f (generic function with 1 method)

julia v0.5.0> f(::Float32) = 1
f (generic function with 2 methods)

julia v0.5.0> f(::Int) = 2
WARNING: Method definition f(Int64) in module Main at REPL[1]:1 overwritten at REPL[3]:1.
f (generic function with 2 methods)

julia v0.5.0> f(::Float64) = 2
f (generic function with 3 methods)

julia v0.5.0> f(1)
2

```

---

<div class="post-metadata">

**Author:** ![barche](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barche/32/79_2.png) [@barche](https://discourse.julialang.org/u/barche)\
**Post date:** [February 25, 2017, 6:12pm UTC](https://discourse.julialang.org/t/unions-vs-adding-methods/2298/12 "2017-02-25T18:12:20Z")

</div>

OK, thanks for the replies, as usual things aren’t as simple as they appear on the surface 🙂 I conclude that for CxxWrap what currently results in a method redefinition warning will become an ambiguity error if I switch to Unions. Since redefinition warnings here indicate that a wrapped C++ function is masked by another, they also must be treated as errors, so I can safely switch to the Union approach.
