I have a situation where I'd like to somehow const...
# announcements
a
I have a situation where I'd like to somehow constrain two generic type parameters where one is the non-null type of the other. Here's a simple example:
Copy code
class Transformer<T, D>(private val seq: Sequence<T>, private val lambda: (T) -> D) {
    fun process(): Sequence<D> = seq.mapNotNull { lambda(it) }
}
An example usage would be:
Copy code
val mySeq = Transformer(sequenceOf("abc"), String::toUpperCase)
However, what if we change the API of the Transformer class to allow the incoming sequence to contain null values but, since these are already filtered out in the
process
function before we call the lambda, we want the lambda parameter to only have to deal with not null T values? Concretely, I'd like this to work:
Copy code
val mySeq = Transformer(sequenceOf("abc", null), String::toUpperCase)
This doesn't compile because T is a nullable String. Is there any way that two generic parameters can be tied like that or some way of specifying that the parameter of the lambda is not null?
z
Give
T
an upper bound of
Any
, and then you can use
T?
to refer to the nullable version.
a
That would indeed work in this case. However, it does lose type info. For example, what if the
seq
property wasn't private? When referenced, it would always give a nullable type, even if the value wasn't nullable.
Copy code
class Transformer<T: Any, D>(val seq: Sequence<T?>, private val lambda: (T) -> D) {
    fun process(): Sequence<D> = seq.filterNotNull().map { lambda(it) }
}

val x = Transformer(sequenceOf("abc"), String::toUpperCase)
val z = x.seq // Sequence<String?> not Sequence<String>
I would like to be able to introduce a generic type that extends another generic type and extends Any (not null) but this doesn't seem possible.
a
Copy code
class Transformer<T, D>(private val seq: Sequence<T?>, private val lambda: (T?) -> D) {
    fun process(): Sequence<D> = seq.mapNotNull { lambda(it) }
}

val mySeq = Transformer(sequenceOf("abc", null)) { it?.toUpperCase() }