# Resolving method ambiguity with Union

**URL:** <https://discourse.julialang.org/t/resolving-method-ambiguity-with-union/121106>\
**Category:** General Usage\
**Tags:** question, ambiguities\
**Created:** [October 9, 2024, 1:21pm UTC](https://discourse.julialang.org/t/resolving-method-ambiguity-with-union/121106 "2024-10-09T13:21:42Z")\
**Posts on this page:** 9\
**Page:** 1

<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:** [October 9, 2024, 1:21pm UTC](https://discourse.julialang.org/t/resolving-method-ambiguity-with-union/121106/1 "2024-10-09T13:21:42Z")

</div>

Suppose I am trying to define a `hvcat` for a user type, and after I deal with the first argument (which can be an `Int`, or a `Tuple{Vararg{Int}`), the methods share a lot of code. So it would be ideal for me to just branch on the first argument and then _implement one method_.

But ambiguities do not allow that. MWE (for just this part):

```julia
julia> struct Foo end

julia> Base.hvcat(blocks_per_row::Union{Tuple{Vararg{Int}}, Int}, foos::Foo...) = Foo()

julia> [Foo() Foo();
       Foo() Foo()]
ERROR: MethodError: hvcat(::Tuple{Int64, Int64}, ::Foo, ::Foo, ::Foo, ::Foo) is ambiguous.

Candidates:
  hvcat(rows::Tuple{Vararg{Int64}}, xs...)
    @ Base abstractarray.jl:2155
  hvcat(blocks_per_row::Union{Int64, Tuple{Vararg{Int64}}}, foos::Foo...)
    @ Main REPL[37]:1

```

Now I could extract the core logic of `hvcat` which does the actual heavy lifting (elided above) to an auxiliary function and have the two methods call that, but I am wondering if there is an easier way.

---

<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:** [October 9, 2024, 1:34pm UTC](https://discourse.julialang.org/t/resolving-method-ambiguity-with-union/121106/2 "2024-10-09T13:34:31Z")

</div>

as an aside:

1. `hvcat(::Int, ...)` has a [generic fallback](https://github.com/JuliaLang/julia/blob/91da4bf9323b79e00e446d6471d3b43d4c8ee4c4/base/abstractarray.jl#L2138) so strictly speaking I do not need to define both methods, but this undocumented so I am not sure if this is something I can rely on).
2. which form actually lowers to `hvcat(::Int, ...)`? Everything I tried lowers to the other method with the tuple.

---

<div class="post-metadata">

**Author:** ![littlelib](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/littlelib/32/209324_2.png) [@littlelib](https://discourse.julialang.org/u/littlelib)\
**Post date:** [October 10, 2024, 1:18am UTC](https://discourse.julialang.org/t/resolving-method-ambiguity-with-union/121106/3 "2024-10-10T01:18:51Z")

</div>

Not really sure this is what you’d want, but annotating the type of matrix seems to be a workaround for the ambiguity issue.

```julia
julia> Foo[Foo() Foo();Foo() Foo()]
2x2 Matrix{Foo}
Foo() Foo()
Foo() Foo()

```

---

<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:** [October 10, 2024, 6:36am UTC](https://discourse.julialang.org/t/resolving-method-ambiguity-with-union/121106/5 "2024-10-10T06:36:53Z")

</div>

> [@littlelib](#):
>
> annotating the type of matrix seems to be a workaround for the ambiguity issue

Sure, because that calls a different method (`typed_hvcat`).

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [October 10, 2024, 6:52am UTC](https://discourse.julialang.org/t/resolving-method-ambiguity-with-union/121106/6 "2024-10-10T06:52:22Z")

</div>

> [@Tamas\_Papp](#):
>
> which form actually lowers to `hvcat(::Int, ...)`? Everything I tried lowers to the other method with the tuple.

I don’t think anything does. The minimal matrix syntax lowering to `hvcat` takes a 1-Tuple:

```julia
julia> Meta.@lower [1;] # nope
:($(Expr(:thunk, CodeInfo(
    @ none within `top-level scope`
1 ─ %1 = Base.vcat(1)
└── return %1
))))

julia> Meta.@lower [1 2] # nope
:($(Expr(:thunk, CodeInfo(
    @ none within `top-level scope`
1 ─ %1 = Base.hcat(1, 2)
└── return %1
))))

julia> Meta.@lower [1 2;] # bingo
:($(Expr(:thunk, CodeInfo(
    @ none within `top-level scope`
1 ─ %1 = Core.tuple(2)
│ %2 = Base.hvcat(%1, 1, 2)
└── return %2
))))

```

I think it’s weird that `hvcat` takes a tuple of integers for each row in the first place when all the integers must be equal. This would be a lot simpler to extend if `hvcat` instead took a Matrix shape `Tuple{Int, Int}` the lowerer figures out.

---

<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:** [October 10, 2024, 7:14am UTC](https://discourse.julialang.org/t/resolving-method-ambiguity-with-union/121106/7 "2024-10-10T07:14:07Z")

</div>

> [@Benny](#):
>
> when all the integers must be equal

No they don’t, try

```julia
A = zeros(1, 2)
Meta.@lower [A;
             1 1]

```

which is perfectly fine.

---

<div class="post-metadata">

**Author:** ![littlelib](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/littlelib/32/209324_2.png) [@littlelib](https://discourse.julialang.org/u/littlelib)\
**Post date:** [October 10, 2024, 7:45am UTC](https://discourse.julialang.org/t/resolving-method-ambiguity-with-union/121106/8 "2024-10-10T07:45:54Z")

</div>

> [@Tamas\_Papp](#):
>
> Sure, because that calls a different method (`typed_hvcat`).

Thank you for the correction. I should’ve checked that before, that was dumb of me.

I’ve been experimenting and searching for solutions, and it seems there’s no way of resolving the ambiguity issue when using Unions.  
Did [find](https://discourse.julialang.org/t/union-types-good-or-bad/46255/18) a somewhat better solution, using `@eval` to generate methods for each types.

```julia
for T in (:(Tuple{Vararg{Int}}), :Int)
    @eval Base.hvcat(blocks_per_row::$T, foos::Foo...)=Foo()
end

```

I guess this is the next best thing you can try when Unions can’t do the job.

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [October 10, 2024, 8:54am UTC](https://discourse.julialang.org/t/resolving-method-ambiguity-with-union/121106/9 "2024-10-10T08:54:28Z")

</div>

> [@Tamas\_Papp](#):
>
> extract the core logic of `hvcat` which does the actual heavy lifting (elided above) to an auxiliary function and have the two methods call that

This is what I’d do, I don’t see anything wrong with it.

---

<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:** [October 10, 2024, 9:09am UTC](https://discourse.julialang.org/t/resolving-method-ambiguity-with-union/121106/10 "2024-10-10T09:09:13Z")

</div>

Since then I discovered that there is a fallback in `Base` method that handles the `::Int` case, and in any case, [nothing lowers to that](https://discourse.julialang.org/t/what-lowers-to-hvcat-int/121107). So it is enough to write the `::Tuple{Vararg{Int}}` method.
