Reputation: 5285
The question isn't about how to test an array for emptiness (arr.length == 0
does this fine). Rather my question is, why does
scala> Array().isEmpty
res1: Boolean = true
work and
scala> val x = Array[String]()
x: Array[String] = Array()
scala> x.isEmpty
res2: Boolean = true
work, but
scala> val y = Array()
y: Array[Nothing] = Array()
scala> y.isEmpty
<console>:13: error: value isEmpty is not a member of Array[Nothing]
y.isEmpty
^
does not?
Upvotes: 5
Views: 8864
Reputation: 7348
EDIT: probably this answer is not correct. But I'm keepeing it here to show how did I try to investigate this issue. To me it looks like a bug in the compiler.
The answer is implicit conversion that exists for Array[T <: AnyRef]
String is AnyRef
, Nothing
is not AnyRef
.
How could you discover this yourself?
In IntelliJ you can see a grey underline under the isEmpty
This means that the method isEmpty
is not a method of Array, but an implicit (a method on a class that has implicit conversion from Array).
Now, to discover the implicit conversion, just click ctrl+q
So when you follow it, you get to this line in the source code -
implicit def refArrayOps[T <: AnyRef](xs: Array[T]): ArrayOps[T] = new ArrayOps.ofRef[T](xs)
That explains that the implicit conversion is on an Array[T] when T extends AnyRef
So back to our case -
String <: AnyRef
, but this doesn't hold for Nothing
Upvotes: 3
Reputation: 3739
As @MichaelZajac points out, Nothing
is a subtype of everything (its counterpart Any
is a supertype of everything). In particular it's also a subtype of AnyRef
. In fact there's an even more general genericArrayOps
which has no type bound at all (e.g. Array[Any]().isEmpty
works)! The implicit conversion allowing you to use isEmpty
should kick in, but of course it doesn't, even though explicitly calling the conversion is fine.
The link @slouc gives is the answer, namely that the Scala compiler treats Nothing
in a special way when doing implicit resolution because Nothing
is the default lower bound for a type when doing type inference.
Now why exactly would it ever be desirable for Nothing
not to be considered in implicit resolution? Well the tricky thing about Nothing
again is that it's a subtype of everything. This means that if at any point Scala infers a type to be Nothing
, every single implicit conversion would immediately become valid. This could hide a type error (you should never have an instance of Nothing
, but when that Nothing
becomes an Int
... well who's to say?). (Note I would love for someone who actually hacks on the compiler to jump in and confirm/deny/elaborate on this)
Upvotes: 4