 # Help understand the role of semicolon in turning a UnitRange to a Vector

I understand the difference between the UnitRange and Array/Vector types. I sort of get the syntax for stacking two ranges and converting them into a vector using `;` and `[]` as in

``````julia> a = [1:3;4:5]
5-element Vector{Int64}:
1
2
3
4
5
``````

But I think I need some hint on how to remember/understand/interpret the usage of semicolon for converting just a single unit range into a vector as in:

``````julia> a = [1:3;]
3-element Vector{Int64}:
1
2
3
``````

The documentation on puncuation gives this description for semicolon:

semicolons separate statements, begin a list of keyword arguments in function declarations or calls, or are used to separate array literals for vertical concatenation

and I am just not able to fit this usage to the above described conversion of a range into a vector.

it’s this.

``````julia> vcat(1:3)
3-element Vector{Int64}:
1
2
3

julia> [1:3;]
3-element Vector{Int64}:
1
2
3

julia> vcat(1:3, 4:6)
6-element Vector{Int64}:
1
2
3
4
5
6

julia> [1:3;4:6]
6-element Vector{Int64}:
1
2
3
4
5
6
``````
4 Likes

I suspected that it should be interpreted like this. Simply a (vertical) concatenation of something with nothing, right?

I don’t see how “with nothing” is a useful concept here. You can concatenate any number of abstract vectors into a vector, any number includes 1 and 0.

3 Likes

Perhaps I am just too biased to see the semicolon as a separator of two things. That is why I somehow easily accepted the syntax `[a;b]` and struggled mentally with `[a;]`. But most probably there is not much more to dig here. I will just remember it. Thanks.

2 Likes

Yes instead of separators I think it’s best to think of `[a, b, ...]`, `[a; b; ...]`, `[a b ...]` and `[a b; c d; ...]` as fancy syntax for four different functions.

Four lines above in your linked documentation page, there’s a description specifically for the case of array literals:

`[;]` vertical concatenation (calling vcat or hvcat)
`[ ]` with space-separated expressions, horizontal concatenation (calling `hcat` or `hvcat` )

In you example:

• `[1:3]` is a special case of `[a, b, ...]` with only one argument `a=1:3`. This is fancy syntax for the `Base.vect` function:

``````julia> Meta.@lower [1:3]
:(\$(Expr(:thunk, CodeInfo(
@ none within `top-level scope'
1 ─ %1 = 1:3
│   %2 = Base.vect(%1)
└──      return %2
))))
``````

So `[1:3]` is simply a vector with one element: `1:3`.

• `[1:3;]` is a special case of `[a; b; ...]` with one argument `1:3`. That’s fancy syntax for `vcat`:

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

The `vcat` function concatenates arrays vertically. Here “array” means any subtype of `AbstractArray` (other types are treated as single-element arrays). And a range such as `1:3` is an `AbstractArray`:

``````julia> supertypes(typeof(1:3))
(UnitRange{Int64}, AbstractUnitRange{Int64}, OrdinalRange{Int64, Int64},
AbstractRange{Int64}, AbstractVector{Int64}, Any)

julia> AbstractVector
AbstractVector{T} where T (alias for AbstractArray{T, 1} where T)
``````

So that’s why the `1:3` range gets “flattened” into three values in the resulting vector.

(As for the remaining cases: `[a b ...]` is fancy syntax for `hcat` and `[a b ...; c d ...; ...]` is fancy syntax for `hvcat`. Both of these also treat their arguments as iterators.)

4 Likes

No idea if this is a correct mental model but, in case it helps, may see it as concatenation with empty `[]`:

``````a=1:3
julia> [a;] == [a;eltype(a)[]]
true
``````
1 Like