Stephan Schroeder
11/25/2019, 11:10 AM[Returns(true) -> x is String]
fun isString(x: Any?): Boolean = x is String
so I was interested in seeing if I can write a reified generic version (https://pl.kotl.in/XNSuwtkvC, which would be pretty useful for custom equals-methods):
inline fun <reified T:Any> T.hasSameClass(other: Any?): Boolean {
contract {
returns(true) implies (other is T)
}
if (this === other) return true
return other!=null && this.javaClass == other.javaClass
}
Unfortunately currently this fails due to âreferences to type parameters are forbidden in contractsâ. References to reified type parameters should be doable (<- my feature request).karelpeeters
11/25/2019, 11:25 AMkarelpeeters
11/25/2019, 11:25 AMval result: List<String> = list.filter { it is String }
to compile.Stephan Schroeder
11/25/2019, 11:30 AMfilterIsInstance
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/filter-is-instance.htmlkarelpeeters
11/25/2019, 11:31 AMkarelpeeters
11/25/2019, 11:32 AMtakeIf
should work too, and maybe you want to filter on multiple things as well and then you need .filterIsInstance<String>().filter { it.length == 5 }
and that's starting to get both slow and ugly.Stephan Schroeder
11/25/2019, 11:38 AMfilter
on itâs own can be applied to all kinds of predicates, type checks is actually quite rare. But the contrats definition (for filter with smar cast) is specific to type checking predicates. Contracts are written into the executing function, but your usecase would require the lambda-parameter to be identifieable as âprovides smart cast guaranteesâ. At the least your usecase is considerably more complicated than my usecase. So I get why the devs when with a specifc filterIsInstance
instead.karelpeeters
11/25/2019, 11:41 AMfilterIsInstance
because contracts didn't even exist back then.
And this very similar to other contracts but on a collection. The KEEP has this as something to consider as well.Stephan Schroeder
11/25/2019, 12:02 PMfun <T,R:T> List<T>.filter( predicate: (T)->Boolean): List<R> {
contract {
"if predicate smart casts T to subtype X" then R = X else R = T"
}
...
}
So 1) you would need the âdoes parameter lambda smart casts itâs argumentâ-functionality which is very sideeffect driven (the type of the lambda doesnât contain this possible smart cast). But isnât the bigger problem that 2) the return type of filter
(either T if the lambda doesnât smartcasts itâs argument or R otherwise) isnât computable from the type definitions given?!? Again, nothing in the definition of predicate
says that itâs smartcasts, so I guess you would need âsecond-level contracts: contractsâ!. Contracts that work on arguments that have contracts.