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 Nothing
streetsofboston
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.