Matthew Pope
08/07/2020, 1:54 AMNothing? in your code anywhere?Zach Klippenstein (he/him) [MOD]
08/07/2020, 2:11 AMsealed class Stuff<out T> {
data class Something<T>(val it: T) : Stuff<T>() {
override fun getOrNull(): T? = it
}
object None : Stuff<Nothing>() {
override fun getOrNull(): Nothing? = null
}
abstract fun getOrNull(): T?
}nanodeath
08/07/2020, 2:11 AMval foo = null does in fact compile, with type Nothing? :)nanodeath
08/07/2020, 2:11 AMMatthew Pope
08/07/2020, 2:16 AMZach Klippenstein (he/him) [MOD]
08/07/2020, 2:16 AMUnit happens to be defined as a type with a single value (like any object), Nothing? is a type that can only have one value.Matthew Pope
08/07/2020, 2:17 AMstreetsofboston
08/07/2020, 4:06 AMNothing is a type without any values (empty set).
T? is a type whose values are in T or is null.
Nothing? has therefore one value (any value in Nothing - which don't exist - or null), and that value is null.
Conversely, the value null has the type Nothing?, and Nothing? is a sub-type of all other types T?. That is why you can assign the value null to every nullable type (T?).
😀Zach Klippenstein (he/him) [MOD]
08/07/2020, 4:20 AMMatthew Pope
08/07/2020, 4:35 AMNothing? that is not forced by an interface or some weird generics, but is still totally contrived. 😏 Consider this code snippet:
when (it) {
null -> println("It's null")
is Int -> println("It's an int")
is Long -> println("It's a long")
}
Maybe you think that is ugly because the first condition is not a type check like the rest of them… you can substitute is Nothing? for the null equality check.Zach Klippenstein (he/him) [MOD]
08/07/2020, 6:02 AMis Nothing? there a lot more confusing than a simple null. The null makes it really clear it's a null check, using Nothing forces you to think much harder.Fabio
08/07/2020, 6:05 AMwhile(true) {
// do work
}
Arduino coders may love this trick 😉Zach Klippenstein (he/him) [MOD]
08/07/2020, 6:14 AMNothing (not nullable), because they can't ever have a value. When the compiler encounters an expression of type Nothing, it knows nothing after it will ever be executed, which is how it can warn about dead code after a return, for example. If something has the type Nothing?, it can still have a value, and code after it might still execute.araqnid
08/07/2020, 9:58 AMreturn and throw are basically expressions of type Nothing (which is why you can put TODO() anywhere, and code after it is dead)Fabio
08/07/2020, 10:55 AMreturn and throw are Unit, but not sure here.
Basically, there's a single object Unit but there's no object that can be of type Nothingstreetsofboston
08/07/2020, 12:00 PMreturn and throw are keywords forming an expression that returns Nothing (not even a Unit) and no code can follow it. Eg return return return return return 5 is an expression that compiles fine...😀araqnid
08/07/2020, 1:02 PMval thing = findThing(id) ?: throw NotFoundException() worksdmitriy.novozhilov
08/07/2020, 2:04 PMNothing? can be usefull. Assume you have some parametrized visitor
abstract class Visitor<R, D> {
abstract fun visitElement(
element: Element,
data: D
): R
...
}
and you want to have visitor which doesn't use any data. In this case you can parametrize D with Nothing?
class MyVisitor : Visitor<String, Nothing?>() {
override fun visitElement(
element: Element,
data: Nothing?
): String {
...
}
...
}
fun test(element: Element) {
val visitor = MyVisitor()
val result = element.accept(visitor, null)
}
Also Unit can be used in this case instead of Nothing?, but it depends of your habbits and codestyleZach Klippenstein (he/him) [MOD]
08/07/2020, 4:40 PMUnit means the author/API explicitly intends there to be only a single possible value. Nothing? means that there are probably some combination of type constraints that mean there won't be a value here, but with other type constraints there probably could be a value.