nwh
07/15/2019, 7:29 PMOptional
? Where there are three valid values: regular value, null, nothing. I'm using a data class so a lateinit var
isn't exactly the best solutionjw
07/15/2019, 7:31 PMnwh
07/15/2019, 7:33 PMobject.value = uselessWrapper(value)
and object.value.get()
, it gets so crowdedstreetsofboston
07/15/2019, 7:44 PMval value: Optional<T>?
, where a null
value is ‘nothing/unknown’, a Optional.None
value is ‘not-present’ and Optional.Some<T>
is an actual regular value?jw
07/15/2019, 7:45 PMnwh
07/15/2019, 7:52 PMgroostav
07/15/2019, 7:54 PMnull
than it does for empty/nothing
to me means this is a very subtle problem. What does null
encode? What does empty
encode? At this point I'd probably make a sealed class that names those two concepts, and go from there. Downstack, where you can be certain you don't care about one of those cases, (eg in a parameter), use a simple nullable-type instead of this sealed class. But if its a field for a state machine, you would need to completely eliminate one of those states to avoid the "useless boilerplate"nwh
07/15/2019, 8:06 PMstreetsofboston
07/15/2019, 8:18 PMsealed class Optional<out T : Any> {
object None : Optional<Nothing>()
object Null : Optional<Nothing>()
data class Some<out T : Any>(val value: T) : Optional<T>()
}
nwh
07/15/2019, 8:22 PMstreetsofboston
07/15/2019, 8:22 PMnot
or component1
operator (use one of them), where you tease out values if it is a Some and short-cut a None value all together (bind
).
private object IsNoneException : Exception()
sealed class Optional<out T> {
object None : Optional<Nothing>()
data class Some<out T>(val value: T) : Optional<T>()
companion object {
fun <T> bind(block: () -> T): Optional<T> = try {
Some(block())
} catch (_: IsNoneException) {
None
}
}
}
operator fun <T> Optional<T>.not(): T {
return when (this) {
is Optional.Some -> value
is Optional.None -> throw IsNoneException
}
}
operator fun <T> Optional<T>.component1(): T {
return when (this) {
is Optional.Some -> value
is Optional.None -> throw IsNoneException
}
}
fun main() {
val optional: Optional<Int?> = Optional.Some(2)
val result1 = Optional.bind {
val value = !optional
if (value != null) value * 2 else 0
}
val result2 = Optional.bind {
val (value) = optional
if (value != null) value * 2 else 0
}
println("$result1 and $result2")
}
nwh
07/15/2019, 9:34 PM