https://kotlinlang.org logo
#getting-started
Title
# getting-started
d

dave08

03/07/2024, 12:42 PM
I have:
Copy code
suspend fun <T> invalidate(block: suspend () -> T = { Unit as T }): T =
        cache.invalidate(key to emptyList(), block = block)

// when using this with the default block I need to provide type information... how can I omit it?
cache.invalidate<Unit>()
c

CLOVIS

03/07/2024, 1:03 PM
Use an overload instead of a default value.
Copy code
suspend fun <T> invalidate(block: suspend () -> T): T = …
suspend fun invalidate(): Unit = invalidate<Unit> {}
This is because
{ Unit as T }
makes no sense: the caller decides what to use as
T
, so you cannot know if
Unit
is a legal value of the type they choose.
👍🏼 1
With your example, consider what happens when running:
Copy code
cache.invalidate<Int>()
(spoiler: CCE)
💥 1
d

dave08

03/07/2024, 1:07 PM
Yeah, thanks, I guess it doesn't really make sense, I was just half expecting that since the lambda is the only one using the
T
parameter and it returns Unit, that it would infer that T can only be Unit... but you're point is good -- since in the end the caller is supposed to decide...
So I guess this is also problematic:
Copy code
override suspend fun <R> invoke(
        name: String,
        type: KSerializer<R>,
        vararg params: Any,
        saveResultIf: (R) -> Boolean,
        block: suspend () -> R
    ): R {
...
            if (config?.nullPlaceholder != null && result == config.nullPlaceholder)
                null as R
            else
                jsonParser.decodeFromString(type, result)
        }
    }
...
Copy code
`null as R
c

CLOVIS

03/07/2024, 1:15 PM
No, this is fine, because
<R>
is a shorthand for
<T : Any?>
, so
null
is a legal value.
Wait no
No it's not, the user could decide to call it with
Int
, so
null
would be forbidden
d

dave08

03/07/2024, 1:16 PM
So what could I do there?
c

CLOVIS

03/07/2024, 1:17 PM
Either you return
R?
, so
null
is always allowed even if the user used
Int
d

dave08

03/07/2024, 1:19 PM
Yeah, well my problem is that the user might want to use it like this:
Copy code
fun someComputation(...): Foo = cache("some-cache") {
  ... this won't return a null, because it'll only cache computation results which will always not be null in this case
}
I will only have a null there if the result of the computation can have a null
But if not, it will never return null either...
So the cast is logical, and I guess there's no real type-safe way out of this except for your previous TypedKacheable proposition (I'm currently working on... but the default will still be this version that's not typed...)
I guess for invalidate at least, it's a good idea to provide an overload, but for this one I'm not sure.
Thanks a lot for the explanation, at least now I'm much more conscious of what I'm doing in this...!
👍 1