Assigning a UnitRange to an array

Hi,

I have a matrix with elements of type UnitRange

a = Array{UnitRange}(undef ,2,2)

I would like to assign a unit range like (200:375) to a range of elements using broadcast.

a[1,:] .= (200:375)

but I get this error

ERROR: DimensionMismatch: array could not be broadcast to match destination

Clearly Julia wants to interpret the UnitRange rather than just assign the array elements to the UnitRange.

Is there a way to achieve what I need?

Thanks
Steve

Have you tried this?

a[1,:] .= Ref(200:375)
3 Likes

Perfect, thanks.

Also, to maintain type stability, you might consider setting a’s element type to a concrete type. UnitRange is a UnionAll, and to specify a concrete type you need to parameterize it with the type of its elements—in this case, UnitRange{Int}:

a = Array{UnitRange{Int}}(undef, 2, 2)

The reason it won’t broadcast is because the range has a length and so will try to broadcast over that length. The Ref works because this has a length one.

As an alternative to the Ref which may in some situations be allocating, you can also wrap it as a 1-tuple or in the StaticArrays Scalar made specifically for this reason:

# Tuple
a[1, :] .= (200:375,)

# Scalar
using StaticArrays
a[1, :] .= Scalar(200:375)

I prefer Scalar as this is more semantic - the next person looking at your code doesn’t have to work out why you used a Ref or a tuple, the reason is right there in the documentation for Scalar.

2 Likes

Huh, didn’t know about Scalar. Definitely feels like something that should be in Base; the Ref trick to cause scalar broadcasting always felt like an ugly hack, especially since you aren’t using it for its mutability.

Just to add maybe part of your confusion stems from the fact that the brackets arround the range don’t do anything here, the key is this difference:

julia> (200:375)
200:375

julia> (200:375,)
(200:375,)

this is a difference between arrays and tuples:

julia> a[1,:] .= [200:375]
2-element view(::Matrix{UnitRange}, 1, :) with eltype UnitRange:
 200:375
 200:375

for tuples just doing (x) isn’t possible because parens are used to group expressions as well, while [x] will create a 1-element vector. You normally don’t want to use [x] though because that has to allocate, hence why people go for (x,), Ref, or Scalar as discussed.

Thanks for all the help here. Scalar looks like the best solution for me.