A related question: Is it intentional that broadcastable
is not explicitly defined for Char
in broadcast.jl
? Instead the default method for iterables is used. String
in contrast is treated as a scalar, as discussed above.
It doesn’t need to be — like Number
, a Char
can act as a 0-dimensional array. (IIRC it used to be that Char
was a subtype of Integer
so it got its behavior then, and kept it when it was split off into its own type.)
I’m sorry, I don’t fully understand. The current definitions include broadcastable(x::Number) = x
and broadcastable(x::Char) = collect(x)
. It seems to me that Char
is the only plain bits type for which broadcastable
calls collect
. (This once threw me off when implementing broadcasting for a custom type.) Do you think this is correct or a bug?
Sorry, I must have misremembered — it must be that Char
is missing some method after all that would allow it to work with broadcast
without the collect
? I’m not sure what it is, since Char
supports size
and getindex
and axes
similar to Number
. What happens if you remove that method and try to broadcast
?
The code
import Base.Broadcast: broadcastable
broadcastable(x::Char) = x
['a','b'] .* 'd'
results in
ERROR: MethodError: no method matching getindex(::Char, ::CartesianIndex{0})
So it appears to be getindex
that doesn’t work.
Seems like a bug (a missing method), since a zero-argument getindex works for Char.
You’re right. If you create such a method for getindex
, then it works:
import Base: getindex
getindex(x::Char, ::CartesianIndex{0}) = x
import Base.Broadcast: broadcastable
broadcastable(x::Char) = x
['a','b'] .* 'c' # works
Is it worth filing this on GitHub?
Seems like it. (If nothing else, it would give a cleaner way to broadcast using Char
, without allocating a temporary array with collect
.)
I’ve created a PR.