https://kotlinlang.org logo
Title
n

nickk

05/23/2019, 4:39 PM
Is it possible to do something like this? I want to avoid switching on each potential type. Does type erasure make it impossible?
data class DataDriver<T>(val valueCalculator: (T) -> Int)

val dataDriver = listOf(
        DataDriver<T1>( ::calcValue1),
        DataDriver<T2>( ::calcValue2)
)

// Using reified worked here
private inline fun <reified T> query(isSubmitted: Boolean): List<T> { 
	return realm.where<T>().equalTo("submitted", isSubmitted).find()
}

fun calcValue1(item: T1) -> Int {
	return 42
}

// But what about here?
// Apply transforms to get a list of calculated items,
// calling the proper query and calculator based on the type.
// Without resorting to type checks for each type.
// IS THIS POSSIBLE?
dataDriver.map {
	query()  // type inference fails here
		.map(::valueCalculator) 
}
k

karelpeeters

05/23/2019, 4:48 PM
I don't think there's a way to iterate over a list of reified types like this, you'll have to go for either reflection of manual type checking.
n

nickk

05/23/2019, 4:50 PM
@karelpeeters Which is kind of slow, right?
k

karelpeeters

05/23/2019, 4:51 PM
Reflection? Things like
where
must use reflection behind the scenes anyway to do something with the reified type, so it's not going to be slower.
(at least that's my guess, I don't know what
where
is from)
d

diesieben07

05/24/2019, 1:33 PM
What you want is not possible. The type of the elements is not retained here and it is not possible to do so without serious refactoring. A list only contains one type, not multiple.
r

ribesg

05/24/2019, 1:35 PM
Yeah you can write
reified
everywhere you want
List
will never retain any type
n

nickk

05/24/2019, 1:41 PM
@ribesg Actually, my issue is here.
dataDriver.map {
    query()  // type inference fails here
        .map(::valueCalculator) 
}
Could I solve this by restricting the type in
query()
?
d

diesieben07

05/24/2019, 1:41 PM
You could, but again, it would then only be one type for all elements in the list.
n

nickk

05/24/2019, 1:43 PM
It would be the base class. So, run-time dispatching to the proper subclass would not work? Is this what you mean?
r

ribesg

05/24/2019, 1:43 PM
The type used in
query
would be the type of the list, it’s simple
d

diesieben07

05/24/2019, 1:44 PM
Correct. For that you would need a variant of
query
that can accept e.g. a
KClass
instead of a reified type parameter.
n

nickk

05/24/2019, 1:48 PM
@diesieben07 But then, I would have to switch on this type. Things like
map
would not work…
d

diesieben07

05/24/2019, 1:51 PM
I am not sure what you mean by that.
n

nickk

05/24/2019, 1:54 PM
I mean, it is not possible to write something like this:
dataDriver.map {
    query()  // type inference fails here
        .map(::valueCalculator) 
}
query()
is a generic function here.
r

ribesg

05/24/2019, 2:05 PM
You could use various calls to
.filterIsInstance<X>()
d

diesieben07

05/24/2019, 2:18 PM
Yes, it is.
dataDriver.map { query(it::class) }
👍 1
But then you need to change
query
to accept
KClass
instead of a reified type parameter
n

nickk

05/24/2019, 2:40 PM
@diesieben07 Thanks, I will give it a try! I do not like reified types anyway. They feel like an ugly workaround that leads to code bloat .