```internal fun Iterable<*>.containerName():...
# stdlib
l
Copy code
internal fun Iterable<*>.containerName(): String {
   return when (this) {
      is List -> "List"
      is Set -> "Set"
      is Map<*, *> -> "Map"
      is ClosedRange<*>, is OpenEndRange<*> -> "Range"
      is Collection -> "Collection"
      else -> "Iterable"
   }
}
Why does this code compiles when
Map
and
Ranges
are not Iterable? AI caught this issue for me and I expected the compiler to 😂
y
Something could be both an
Iterable
and a
Map
(probably, although you might run into signature overload issues)
1
l
Makes perfect sense. Thanks @Youssef Shoaib [MOD]!
o
1..2
gives you an
IntRange
, which is an
IntProgression
, which is an
Iterable<Int>
. It is also an
Open/ClosedRange
The Progression provides iteration and the Range provides start/end values
1
The
Map
case makes much less sense though. I don't know if there are any standard Maps that implement Iterable.
l
They usually provide iterators but are not iterable, just like Sequence
a
I’ve always felt that Java’s Map interface is not a true “collection”, as it does not expose an iterator. Strictly speaking the Map should have base type of
Collection<Map.Entry<K,V>>
this would have made the whole API more consistent.
t
It comes down to whether the classifier of the type is
final
or
open
:
Copy code
//final classifiers
class Class
enum class EnumClass

//open classifiers
interface Interface
open class OpenClass
abstract class AbstractClass
sealed class SealedClass
For example:
Copy code
//(just for clarity in example)
typealias FinalClassifier = Class
typealias OpenClassifier = Interface

fun FinalClassifier.test() {
    when (this) {
        is Class -> {} //OK
        is EnumClass -> {} //Error
        is Interface -> {} //Error
        is OpenClass -> {} //Error
        is AbstractClass -> {} //Error
        is SealedClass -> {} //Error
    }
}

fun OpenClassifier.test() {
    when (this) {
        is Class -> {} //Error
        is EnumClass -> {} //Error
        is Interface -> {} //OK
        is OpenClass -> {} //OK
        is AbstractClass -> {} //OK
        is SealedClass -> {} //OK
    }
}
The extendable types (declared with open classifiers) are given more "leeway", because it is possible for a subtype to inherit/extend them and the target type it is checked against