# \`(x, y)\` works but \`x =\> y\` doesn't

**URL:** <https://discourse.julialang.org/t/x-y-works-but-x-y-doesnt/62703>\
**Category:** General Usage\
**Created:** [June 10, 2021, 9:09pm UTC](https://discourse.julialang.org/t/x-y-works-but-x-y-doesnt/62703 "2021-06-10T21:09:06Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![Samuel\_Ainsworth](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/samuel_ainsworth/32/15644_2.png) [@Samuel\_Ainsworth](https://discourse.julialang.org/u/Samuel_Ainsworth)\
**Post date:** [June 10, 2021, 9:09pm UTC](https://discourse.julialang.org/t/x-y-works-but-x-y-doesnt/62703/1 "2021-06-10T21:09:06Z")

</div>

This really seems like a bug to me, but perhaps I’m missing some kind of obscure difference between `(x, y)` and `x => y` syntax…

```julia
import Base: ==, big
import IntervalArithmetic: Interval

struct Foo <: Real
  v
end

# Necessary for printing
==(x::Foo, y::Float64) = x.v == y
big(x::Foo) = big(x.v)

# This works...
@show ("abc", Interval(Foo(0.0), Foo(1.0)))
# But this doesn't work...
@show "abc" => Interval(Foo(0.0), Foo(1.0))

```

What’s going on here? Why can I no haz arrow pairs?

---

<div class="post-metadata">

**Author:** ![Samuel\_Ainsworth](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/samuel_ainsworth/32/15644_2.png) [@Samuel\_Ainsworth](https://discourse.julialang.org/u/Samuel_Ainsworth)\
**Post date:** [June 10, 2021, 9:14pm UTC](https://discourse.julialang.org/t/x-y-works-but-x-y-doesnt/62703/2 "2021-06-10T21:14:01Z")

</div>

Btw, the error message is

```julia
ERROR: LoadError: MethodError: no method matching atomic(::Type{Interval{Foo}}, ::Interval{Foo})
Closest candidates are:
  atomic(::Type{Interval{T}}, ::Interval) where T<:AbstractFloat at /Users/skainswo/.julia/packages/IntervalArithmetic/UR6Qe/src/intervals/conversion.jl:122
  atomic(::Type{Interval{T}}, ::S) where {T<:AbstractFloat, S<:Real} at /Users/skainswo/.julia/packages/IntervalArithmetic/UR6Qe/src/intervals/conversion.jl:95
Stacktrace:
 [1] convert(#unused#::Type{Interval{Foo}}, x::Interval{Foo})
   @ IntervalArithmetic ~/.julia/packages/IntervalArithmetic/UR6Qe/src/intervals/conversion.jl:20
 [2] Pair
   @ ./pair.jl:12 [inlined]
 [3] Pair(a::String, b::Interval{Foo})
   @ Base ./pair.jl:15
 [4] top-level scope
   @ show.jl:955
in expression starting at /Users/skainswo/dev/research/julia/boxes/src/bug.jl:16

```

which doesn’t make any sense considering that `convert(::Type{Interval{Foo}}, x::Interval{Foo})` is implemented here: [IntervalArithmetic.jl/conversion.jl at master · JuliaIntervals/IntervalArithmetic.jl · GitHub](https://github.com/JuliaIntervals/IntervalArithmetic.jl/blob/master/src/intervals/conversion.jl#L19).

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [June 10, 2021, 10:38pm UTC](https://discourse.julialang.org/t/x-y-works-but-x-y-doesnt/62703/3 "2021-06-10T22:38:08Z")

</div>

> [@Samuel\_Ainsworth](#):
>
> but perhaps I’m missing some kind of obscure difference between `(x, y)` and `x => y` syntax

They do different things, so I’m not sure why you expect to behave the same.

The difference is that a tuple just takes the two values as they are, in the stacktrace of the `Pair` constructor you can see `convert(::Type{Interval{Foo}}, x::Interval{Foo})` is called, and that function fails because it internally tries to call an undefined method

---

<div class="post-metadata">

**Author:** ![Samuel\_Ainsworth](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/samuel_ainsworth/32/15644_2.png) [@Samuel\_Ainsworth](https://discourse.julialang.org/u/Samuel_Ainsworth)\
**Post date:** [June 10, 2021, 10:46pm UTC](https://discourse.julialang.org/t/x-y-works-but-x-y-doesnt/62703/4 "2021-06-10T22:46:15Z")

</div>

At the risk of getting sidetracked, why does Julia have redundant `Pair` and tuple constructs?

> [@giordano](#):
>
> The difference is that a tuple just takes the two values as they are, in the stacktrace of the `Pair` constructor you can see `convert(::Type{Interval{Foo}}, x::Interval{Foo})` is called, and that function fails because it internally tries to call an undefined method

But why doesn’t it just call the`convert` implementation here: [https://github.com/JuliaIntervals/IntervalArithmetic.jl/blob/master/src/intervals/conversion.jl#L19](https://github.com/JuliaIntervals/IntervalArithmetic.jl/blob/master/src/intervals/conversion.jl#L19)?

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [June 10, 2021, 10:56pm UTC](https://discourse.julialang.org/t/x-y-works-but-x-y-doesnt/62703/5 "2021-06-10T22:56:02Z")

</div>

> [@Samuel\_Ainsworth](#):
>
> But why doesn’t it just call the `convert` implementation here

Yeah, that does seem odd. I don’t quite understand what’s happening. You might have to file an issue at the IntervalArithmetic.jl repo.

---

<div class="post-metadata">

**Author:** ![Jeff\_Emanuel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff_emanuel/32/15440_2.png) [@Jeff\_Emanuel](https://discourse.julialang.org/u/Jeff_Emanuel)\
**Post date:** [June 10, 2021, 11:05pm UTC](https://discourse.julialang.org/t/x-y-works-but-x-y-doesnt/62703/6 "2021-06-10T23:05:55Z")

</div>

> [@Samuel\_Ainsworth](#):
>
> At the risk of getting sidetracked, why does Julia have redundant `Pair` and tuple constructs?

See [`Pair{A,B}` vs. `Tuple{A,B}` - #5 by Tamas\_Papp](https://discourse.julialang.org/t/pair-a-b-vs-tuple-a-b/942/5) and links therein.

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [June 10, 2021, 11:07pm UTC](https://discourse.julialang.org/t/x-y-works-but-x-y-doesnt/62703/7 "2021-06-10T23:07:02Z")

</div>

> [@Samuel\_Ainsworth](#):
>
> At the risk of getting sidetracked, why does Julia have redundant `Pair` and tuple constructs?

Redundant? They have different semantics: tuple is a container of arbitrary size, `Pair` is only for, well, pairs of the type key =\> value.

> [@Samuel\_Ainsworth](#):
>
> But why doesn’t it just call the `convert` implementation here:

That bit confuses me as well at the moment but I agree with Cameron that sounds like a but in IntervalArithmetic.jl

---

<div class="post-metadata">

**Author:** ![Samuel\_Ainsworth](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/samuel_ainsworth/32/15644_2.png) [@Samuel\_Ainsworth](https://discourse.julialang.org/u/Samuel_Ainsworth)\
**Post date:** [June 10, 2021, 11:08pm UTC](https://discourse.julialang.org/t/x-y-works-but-x-y-doesnt/62703/8 "2021-06-10T23:08:13Z")

</div>

I’ve opened [What is required to use custom types in `Interval`s? · Issue #476 · JuliaIntervals/IntervalArithmetic.jl · GitHub](https://github.com/JuliaIntervals/IntervalArithmetic.jl/issues/476#issuecomment-859099814)

---

<div class="post-metadata">

**Author:** ![Samuel\_Ainsworth](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/samuel_ainsworth/32/15644_2.png) [@Samuel\_Ainsworth](https://discourse.julialang.org/u/Samuel_Ainsworth)\
**Post date:** [June 10, 2021, 11:10pm UTC](https://discourse.julialang.org/t/x-y-works-but-x-y-doesnt/62703/9 "2021-06-10T23:10:09Z")

</div>

> [@giordano](#):
>
> Redundant? They have different semantics: tuple is a container of arbitrary size, `Pair` is only for, well, pairs of the type key =\> value.

I’m not aware of any other languages that make this distinction. In most languages I’ve experienced tuple is explicitly not a container of arbitrary size. That’s what distinguishes it from arrays etc. Instead it’s used as a value type. (Fwiw I’m coming from a background of Python, Haskell, Ocaml, F#, C++, Scala, etc but perhaps there are others I’m missing)

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [June 10, 2021, 11:13pm UTC](https://discourse.julialang.org/t/x-y-works-but-x-y-doesnt/62703/10 "2021-06-10T23:13:26Z")

</div>

Ha, I think he meant that you can make a tuple of any size, not that you can change the size of an existing tuple. 🙂

---

<div class="post-metadata">

**Author:** ![Samuel\_Ainsworth](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/samuel_ainsworth/32/15644_2.png) [@Samuel\_Ainsworth](https://discourse.julialang.org/u/Samuel_Ainsworth)\
**Post date:** [June 10, 2021, 11:14pm UTC](https://discourse.julialang.org/t/x-y-works-but-x-y-doesnt/62703/11 "2021-06-10T23:14:55Z")

</div>

Ah I see… But then I’m not sure why the distinction with `Pair`…

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [June 10, 2021, 11:18pm UTC](https://discourse.julialang.org/t/x-y-works-but-x-y-doesnt/62703/12 "2021-06-10T23:18:28Z")

</div>

To summarize the main differences between `Tuple` and `Pair`, which I’m mostly stealing from the link provided by @Jeff_Emanuel:

- You can make a tuple with any number of elements, but a pair can only have two elements.
- We have special syntax for Pair: `=>`. That syntax doesn’t quite make sense for tuples, since tuples can have more than two elements.
- Tuples are covariant, whereas pairs are invariant:

```julia
julia> (1, 1) isa Tuple{Real, Real}
true

julia> (1 => 1) isa Pair{Real, Real}
false

```

That being said, I often use two element tuples instead of pairs. Pairs do typically imply a `key => value` directionality.

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [June 10, 2021, 11:26pm UTC](https://discourse.julialang.org/t/x-y-works-but-x-y-doesnt/62703/13 "2021-06-10T23:26:39Z")

</div>

> [@Samuel\_Ainsworth](#):
>
> Fwiw I’m coming from a background of Python, Haskell, Ocaml, F#, C++, Scala, etc but perhaps there are others I’m missing

Then I guess you have heard of [`std::tuple`](https://en.cppreference.com/w/cpp/utility/tuple) and [`std::pair`](https://en.cppreference.com/w/cpp/utility/pair) in C++?

---

<div class="post-metadata">

**Author:** ![Samuel\_Ainsworth](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/samuel_ainsworth/32/15644_2.png) [@Samuel\_Ainsworth](https://discourse.julialang.org/u/Samuel_Ainsworth)\
**Post date:** [June 10, 2021, 11:43pm UTC](https://discourse.julialang.org/t/x-y-works-but-x-y-doesnt/62703/14 "2021-06-10T23:43:12Z")

</div>

True, forgot about that… I would argue that the distinction doesn’t make any sense in c++ either though

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [June 10, 2021, 11:45pm UTC](https://discourse.julialang.org/t/x-y-works-but-x-y-doesnt/62703/15 "2021-06-10T23:45:11Z")

</div>

Practically speaking, `Pair` allows you to have the syntax `=>` and dispatch on it without clashing with generic tuples, which are a much lower level concept. Is that enough of a distinction? As I’m trying to say, they have different semantics.

---

<div class="post-metadata">

**Author:** ![Samuel\_Ainsworth](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/samuel_ainsworth/32/15644_2.png) [@Samuel\_Ainsworth](https://discourse.julialang.org/u/Samuel_Ainsworth)\
**Post date:** [June 10, 2021, 11:54pm UTC](https://discourse.julialang.org/t/x-y-works-but-x-y-doesnt/62703/16 "2021-06-10T23:54:31Z")

</div>

Sure, but scala also offers the `x -> y` syntax and just desugars it into a pair `(x, y)`. The one thing that makes some sense to me is that tuples are covariant but `Pair`s are invariant. But even then I don’t understand why make `Pair`s invariant? Are they mutable?

The argument that this is obviously necessary in the first place seems to be invalidated by the fact that there exist so many extremely successful and well-considered language designs that don’t have separate pair and tuple types. Why add complexity?

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [June 11, 2021, 12:08am UTC](https://discourse.julialang.org/t/x-y-works-but-x-y-doesnt/62703/17 "2021-06-11T00:08:26Z")

</div>

You may have missed

> [@giordano](#):
>
> and dispatch on it without clashing with generic tuples

But I don’t have much to add to what has been already said in the discussion on the same topic that has been linked above.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [June 11, 2021, 12:42am UTC](https://discourse.julialang.org/t/x-y-works-but-x-y-doesnt/62703/18 "2021-06-11T00:42:47Z")

</div>

> [@Samuel\_Ainsworth](#):
>
> But even then I don’t understand why make `Pair` s invariant? Are they mutable?

All paratetric types in julia are invariant other than `Tuple`. This is largely for historical reasons as far as I understand. `Tuple` is a very special type that you couldn’t implement in the language itself.

> [@Samuel\_Ainsworth](#):
>
> The argument that this is obviously necessary in the first place seems to be invalidated by the fact that there exist so many extremely successful and well-considered language designs that don’t have separate pair and tuple types. Why add complexity?

🤷‍♂️

Most languages don’t have multiple dispatch, so the name of a type matters less in those languages. This is only extra complexity if you come to julia with baggage from other languages. They’re just different types.

It’s like asking why `Complex{Int}(1, 2)` is a different type from `Rational{Int}(1, 2)`. Sure, they’re both parametric structs with identical layouts, but they have **completely different, unrelated semantic meanings**.
