# Why is splatting a non-iteratable allowed?

**URL:** <https://discourse.julialang.org/t/why-is-splatting-a-non-iteratable-allowed/42818>\
**Category:** Internals & Design\
**Created:** [July 10, 2020, 2:33am UTC](https://discourse.julialang.org/t/why-is-splatting-a-non-iteratable-allowed/42818 "2020-07-10T02:33:52Z")\
**Posts on this page:** 11\
**Page:** 2

<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:** [July 10, 2020, 9:53pm UTC](https://discourse.julialang.org/t/why-is-splatting-a-non-iteratable-allowed/42818/21 "2020-07-10T21:53:30Z")

</div>

Ah, so this is even more confusing than I first realized! Although I’m sympathetic to more advanced use cases the fact that so many newcomers to the language are tripping over this reminds me of a famous Donald Norman quote:

> Change the attitude toward errors. Think of an object’s user as attempting to do a task, getting there by imperfect approximations. Don’t think of the user as making errors; think of the actions as approximations of what is desired.

Through participating in this thread, I’m beginning to feel as though I need to read a manual just to be able to using floating point numbers in Julia!

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [July 10, 2020, 10:02pm UTC](https://discourse.julialang.org/t/why-is-splatting-a-non-iteratable-allowed/42818/22 "2020-07-10T22:02:50Z")

</div>

> [@Samuel\_Ainsworth](#):
>
> Through participating in this thread, I’m beginning to feel as though I need to read a manual just to be able to using floating point numbers in Julia!

Two things:

1. Nothing of this applies to floating numbers specifically, it applies to all `Number`s.
2. I really recommend anyone in any language that has floating numbers and that will make use of them to read a [manual about floating point numbers](https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html). There is so much misconception around them. I say that because I was one of those programmers that were never sure if their computations would be safe to do using floating point numbers.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [July 10, 2020, 10:05pm UTC](https://discourse.julialang.org/t/why-is-splatting-a-non-iteratable-allowed/42818/23 "2020-07-10T22:05:17Z")

</div>

And:

1. You did post in #dev, not #user. The answers to why are always going to be deeper and more complicated than the answers to how. You definitely don’t need to know this to know how to use numbers. 🙂

---

<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:** [July 10, 2020, 10:12pm UTC](https://discourse.julialang.org/t/why-is-splatting-a-non-iteratable-allowed/42818/24 "2020-07-10T22:12:33Z")

</div>

Ah, yeah floating point numbers were a dangerous example! Indeed I’m familiar with all the usual vagaries of floating point numbers. Really the point I was hoping to make here was the relative complexity of number types in Julia for a user that already understands their machine representations and so on.

And apologies if this was not the appropriate channel! I figured this fell more into the realm of language design discussion than user help type thing.

---

<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:** [July 10, 2020, 10:17pm UTC](https://discourse.julialang.org/t/why-is-splatting-a-non-iteratable-allowed/42818/25 "2020-07-10T22:17:45Z")

</div>

One thing I feel I should mention is that I’d be much more sympathetic of your view here @Samuel_Ainsworth if the iteration behaviour of numbers were something ad-hoc in julia. However, the way things like iteration and multi-dimensional indexing were defined is actually something that emerged out of a small set of simple, powerful principals.

It’s very common in things like mathematics or logical systems that when you start with a small set of general principals, surprising consequences of those principals emerge.

For me, I find the principals behind the iteration and multidimensional indexing protocols to be very compelling, so I’m quite biased to make room in my worldview for surprising consequences that come out of these principals.

If we were just winging it and doing these things on a case by case basis, I probably wouldn’t have chosen to have numbers be iterable or indexable. But taken in the wider context of the rest of julia, I think the behaviour has a an appealing and useful consistency. Changing it would weaken the principals that drive iteration and indexing in Julia.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [July 10, 2020, 10:19pm UTC](https://discourse.julialang.org/t/why-is-splatting-a-non-iteratable-allowed/42818/26 "2020-07-10T22:19:28Z")

</div>

I think the only really tricky thing here is that numbers behave like immutable zero-dimensional arrays, as opposed to 1-element vectors or 1×1 matrices. This is the right kind of array for a scalar to behave as, but it’s a little unintuitive that a zero-dimensional array has one element, which is because the product of zero things is 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:** [July 11, 2020, 6:18am UTC](https://discourse.julialang.org/t/why-is-splatting-a-non-iteratable-allowed/42818/27 "2020-07-11T06:18:07Z")

</div>

> [@Mason](#):
>
> But taken in the wider context of the rest of julia, I think the behaviour has a an appealing and useful consistency.

From a math perspective, possibly yes.

But for generic programming, it is problematic if an API extension replacing numbers with something else would be feasible (there are many examples of this in the Julia ecosystem), _but_ the implementation turns out to rely on the fact that they are iterable.

One of the key ideas that make Julia powerful is that very few things are “special”. Numbers aren’t, in two ways:

1. the user could implement their own, equally efficient numerical type,

2. arrays and collections of numbers have no distinguished role, other element types are equally efficient (provided they are bits types etc)

The only exception is that they are iterable collections of themselves. So I do think that this is rather _ad hoc_.

> [@StefanKarpinski](#):
>
> numbers behave like immutable zero-dimensional arrays

But they don’t really — that would require `1 isa AbstractArray{Int,0}`, to be consistent with the rest of the language. Numbers behave like this for the purposes of the iteration protocol, but not otherwise.

I don’t think that this is a _major_ wart in Julia, and I can see that is may have been appealing from a certain perspective. But in retrospect, I don’t think this turned to be a fortunate design choice — which is fine, designing semantics for a language is really hard to get right even after multiple iterations.

I think we should just admit that and try to change it. When 2.0 is on the horizon, I will be tempted to take a stab at fixing this (but I am really hoping that someone beats me to it 😉).

---

<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:** [July 11, 2020, 3:18pm UTC](https://discourse.julialang.org/t/why-is-splatting-a-non-iteratable-allowed/42818/28 "2020-07-11T15:18:32Z")

</div>

> [@Tamas\_Papp](#):
>
> One of the key ideas that make Julia powerful is that very few things are “special”. Numbers aren’t, in two ways:
> 
> 1. the user could implement their own, equally efficient numerical type,
> 2. arrays and collections of numbers have no distinguished role, other element types are equally efficient (provided they are bits types etc)
> 
> The only exception is that they are iterable collections of themselves. So I do think that this is rather _ad hoc_ .

How is this something that’s special about numbers? This is true of _any_ zero dimensional type.

> [@Tamas\_Papp](#):
>
> > [@StefanKarpinski](#):
> >
> > numbers behave like immutable zero-dimensional arrays
> 
> But they don’t really — that would require `1 isa AbstractArray{Int,0}` , to be consistent with the rest of the language. Numbers behave like this for the purposes of the iteration protocol, but not otherwise.

Emphasis on Stefan saying ‘like’. I can’t read his mind, but I assumed he just mentioned array because it’s the most encompassing example of an example fulfilling the multidimensional iteration protocol, not because he believes you have to be an array to implement the protocol.

Types are allowed to partake in the interation protocol and define things like dimensionality despite not being arrays. In addition to `Number`, both `Char` and `Ref` are zero dimensional, indexable containers. `Char` is immutable and `Ref` is mutable.

```julia
julia> 'a' isa AbstractArray, Ref("hi") isa AbstractArray
false, false

julia> ndims('a'), ndims(Ref("hi"))
(0, 0)

julia> 'a'[], Ref("hi")[]
('a', "hi")

julia> size(Ref("hi")), size('a')
((), ())

```

---

<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:** [July 11, 2020, 5:00pm UTC](https://discourse.julialang.org/t/why-is-splatting-a-non-iteratable-allowed/42818/29 "2020-07-11T17:00:13Z")

</div>

> [@Mason](#):
>
> How is this something that’s special about numbers? This is true of _any_ zero dimensional type.

I don’t know what a “zero dimensional type” is. Does it simply mean `size(::T) = ()`? In which case yes, if `T` implements the `AbstractArray` interface, it is of course implied that it is a collection of itself. Numbers are an odd duck since they don’t claim to implement the `AbstractArray` interface, but iterate as if they did. Which is of course fine, it just doesn’t help with the rationalization of thinking that they are 0-dimensional arrays, when they aren’t really.

Just to clarify, I mean that numbers are special in that eg if `x::T isa Number`, it behaves like an iterator with size `()`. This does not hold in general for most types (that are not some kind of collection). Note that the issue is well-known and generally accepted as valid (even if the decision was not to fix). See eg

> <https://github.com/JuliaLang/julia/issues/7903>
>
> @StephenVavasis \[has pointed out\](https://groups.google.com/forum/#!topic/julia-…users/g7PBys0\_6Y8) some rather confusing behavior of the \`in\` operator, including:
> 
> \`\`\` jl
> julia\> VERSION
> v"0.3.0-rc2+12"
> 
> julia\> x = IntSet(\[3,5\])
> IntSet(\[3, 5\])
> 
> julia\> in(3,x)
> true
> 
> julia\> in(x,3)
> false
> 
> julia\> in("abc",19)
> false
> 
> julia\> in(19,"abc")
> false
> \`\`\`
> 
> Worse still is this:
> 
> \`\`\` jl
> julia\> 97 in "abc"
> true
> \`\`\`
> 
> This issue is to discuss what, if anything, we can do to reduce some of this confusion.

Suggestions for other types come up from time to time, eg

> <https://github.com/JuliaLang/julia/issues/29877>
>
> Would it make sense to define \`Base.iterate(::Nothing) = nothing\` ?
> 
> HTTP.jl h…as a generic interface that accepts anything iterable.
> A user has reported \`method matching iterate(::Nothing)\` when they passed \`nothing\`.
> 
> It seems that \`eltype\` is already defined.
> \`\`\`julia
> julia\> eltype(nothing)
> Any
> \`\`\`
> 
> But, \`HasEltype\`, \`HasShape\` and \`HasLength\` are not.

> <https://github.com/JuliaLang/julia/issues/18509>
>
> \`\`\` julia
> julia\> setdiff(\[1,2\], 1)
> 1-element Array{Int64,1}:
> 2
> \`\`\`
> 
> but with sy…mbols it doesn't work:
> 
> \`\`\` julia
> julia\> setdiff(\[:a, :b\], :a)
> \--------------------------------------------------------------------------------
> MethodError Stacktrace (most recent call last)
> \[#2\] — setdiff(::Array{Symbol,1}, ::Symbol)
> ⌙ at array.jl:1466
> 
> \[#1\] — union!(::Set{Any}, ::Symbol)
> ⌙ at set.jl:63
> 
> MethodError: no method matching start(::Symbol)
> Closest candidates are:
> start(::SimpleVector) at essentials.jl:170
> start(::Base.MethodList) at reflection.jl:258
> start(::IntSet) at intset.jl:184
> \`\`\`
> 
> As per the error message, this is apparently because
> 
> \`\`\` julia
> julia\> start(1)
> false
> 
> julia\> start(:a)
> MethodError: no method matching start(::Symbol)
> Closest candidates are:
> start(::SimpleVector) at essentials.jl:170
> start(::Base.MethodList) at reflection.jl:258
> start(::IntSet) at intset.jl:184
> \`\`\`
> 
> Is there a rationale for this? Or can we add iteration to symbols?
> 
> Alternatively, is there a way to ensure something is an array for \`setdiff\` to work?
> I guess using \`\[v;\]\`, but this feels hacky.

Whenever these are rejected (which, again, I agree with), it implicitly means that numbers get special treatment.

> [@Mason](#):
>
> Types are allowed to partake in the interation protocol and define things like dimensionality despite not being arrays.

I am aware of this 😉 The issue is why numbers do this, and why not other types we think of as atoms. (The other basic type that does this is `Char`. AFAIK `Ref` was meant to be something like a container).

---

<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:** [July 11, 2020, 8:58pm UTC](https://discourse.julialang.org/t/why-is-splatting-a-non-iteratable-allowed/42818/30 "2020-07-11T20:58:25Z")

</div>

> [@Tamas\_Papp](#):
>
> I don’t know what a “zero dimensional type” is. Does it simply mean `size(::T) = ()` ? In which case yes, if `T` implements the `AbstractArray` interface, it is of course implied that it is a collection of itself. Numbers are an odd duck since they don’t claim to implement the `AbstractArray` interface, but iterate as if they did. Which is of course fine, it just doesn’t help with the rationalization of thinking that they are 0-dimensional arrays, when they aren’t really.

It’s not an array interface though. It’s a language wide, systematic way of talking about the dimensional of objects. Having such an interface is vital to things like broadcasting working consistently throughout the language.

> [@Tamas\_Papp](#):
>
> Just to clarify, I mean that numbers are special in that eg if `x::T isa Number` , it behaves like an iterator with size `()` . This does not hold in general for most types (that are not some kind of collection). Note that the issue is well-known and generally accepted as valid (even if the decision was not to fix). See eg

Things either have a notion of dimensionality and indexing or they don’t. We know that numbers are scalars, so it makes sense to make them satisfy the interface of zero dimensional objects. If I define some random type `struct Foo end`, Julia can’t know a-priori what sort of object I intend it to be so it doesn’t try to guess.

All other zero dimensional objects in the language that I know of implement this interface, so I’d say making `Number` opt out of it would be ‘special casing’, not opting in.

---

<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:** [July 12, 2020, 6:34am UTC](https://discourse.julialang.org/t/why-is-splatting-a-non-iteratable-allowed/42818/31 "2020-07-12T06:34:06Z")

</div>

> [@Mason](#):
>
> We know that numbers are scalars, so it makes sense to make them satisfy the interface of zero dimensional objects.

This is the key point here. We don’t “know” that numbers are 0-dimensional objects. That’s a convention that some fields use, and it has its advantages. But for a programming language, this is a design choice like any other, with various trade-offs.

> [@Mason](#):
>
> Julia can’t know a-priori what sort of object I intend it to be so it doesn’t try to guess

Precisely — this means that an API which accepts a number and relies on it being iterable is hard to extend to other kinds of objects which don’t intend to be iterable collections of themselves.

[Previous page](https://discourse.julialang.org/t/why-is-splatting-a-non-iteratable-allowed/42818.md?page=1)
