I'm trying to write a Kotlin contract so I can get...
# announcements
m
I'm trying to write a Kotlin contract so I can get smart casts in code calling my function, but this syntax doesn't work, what's the correct way to achieve this?
s
I haven’t really worked with contracts yet, but wouldn’t the correct
implies
predicate be closer to
objects is Array<Any>
also if I’m reading this right, are you trying to use this for a sort of multi-let situation where you’re checking if multiple objects are null?
m
Correct, is there something existing for this situation?
This doesn't work either
s
right, that makes sense
Honestly I’m not sure so I can’t say definitely either way, but I don’t believe there’s a way to do it within the current constraints of the contracts and type system
considering that
vararg objects
is really just a bunch of syntax sugar for variadics that results in getting an
Array<T>
passed in without having to make callers write
function(arrayOf(...))
there isn’t really a good way to relay to the type system via a function that all variables you called this
notNull()
function with can now be safely smart-casted to non-null types
m
So is there any way to improve this
if
statement?
I'm considering keeping my
notNull()
function without the contract, and just using
!!
inside which is guaranteed to be safe, but still doesn't feel right.
s
I’m really not certain, someone else who knows the contracts system is probably gonna have to step in to give you a definitive answer, sorry 😕
m
Ok thank you for your help. 🙂
s
If you find yourself doing this kind of thing a lot, you could consider factoring the logic out into a small handful of utility methods
I’ve never actually used it myself before, but I do have this saved in my “kotlin junk drawer” of sorts
Copy code
inline fun <A, B, C, R> where(a: A?, b: B?, c: C?, block: (A, B, C) -> R?): R? = if (
    a != null &&
    b != null &&
    c != null
  ) block(a, b, c) else null
contrived example:
Copy code
fun frobnicate(i: Int?, s: String?, c: Char?) {
  where(i, s, c) { int, string, char ->
    println(int.toString() + string + char)
  }
}
m
That would work, but the calling code now has to rename (or shadow) all the variables in the lambda. 😕
s
you’re absolutely right, it’s not the most convenient
tradeoffs, I suppose 😕
k
I guess you could copy/paste or even generate code for this for 1 to 10 parameters, that should work.