Hey, was wondering if it was possible to pass `Not...
# getting-started
t
Hey, was wondering if it was possible to pass
Nothing
to a reified type, or something similar?
g
A type that does not have a run-time representation (for example, a non-reified type parameter or a fictitious type like
Nothing
) cannot be used as an argument for a reified type parameter. ©️ Kotlin docs
t
Yeah thought so, do you know of any substitution I can use to just represent no type?
g
No, I don't know. But, well, I don't quite understand what you really want to see. Could you maybe show any use case? Because just types in Kotlin is very wide class, whereas class of reifiable types is much smaller. And if I am right, "no type" can not even be represented in Kotlin type system (at least because almost everything has type (at least
Nothing
)).
t
Yeah of course, let me just try to figure out a way to quickly explain this 😅
So I'm making a query to my API that will respond with a
ServiceResponse.Success
or
ServiceResponse.Failure
, they just represent whether the request to the API was successful or if an error occurred. I pass a generic to these to define a property called
data
in each of them and whenever I don't expect any data back from the API I just pass
Nothing
, so an example of what I do is this.
ServiceResponse.Failure<Nothing>()
So I have another function that I use to send this Http request to the API then I use kotlinx serialization to decode the returned JSON and do whatever I need to on that.
Copy code
protected suspend inline fun <reified T, reified B> bodiedRequestWithResponse(
    request: ServiceRequest<B>
) : ServiceResponse<T> {
    val (endpoint, type, body) = request
    val con = establishConnection(endpoint, type)
        ?: return ServiceResponse.Failure<Nothing>("connection failed.")

    return JSON.decodeFromString(con.attachBodyAndDecode(body))
}
That's the solution I'm using for now just to get something working but
attachBodyAndDecode
takes the custom body I pass to the request and puts it onto the request then I decode that string retrieved. But if I don't expect any data back I can't use
Nothing
because it's an invalid reified type.
For now what I'm doing is I just have two functions and I manually define one with Nothing and the other takes the generic
Copy code
protected suspend inline fun request(
        request: ServiceRequest<Nothing>
    ) : ServiceResponse<Nothing> {
        val (endpoint, type) = request
        val con = establishConnection(endpoint, type)
            ?: return ServiceResponse.Failure("connection failed.")

        return JSON.decodeFromString(con.decodeStream())
    }

    protected suspend inline fun <reified T> requestWithResponse(
        request: ServiceRequest<Nothing>
    ) : ServiceResponse<T> {
        val (endpoint, type) = request
        val con = establishConnection(endpoint, type)
            ?: return ServiceResponse.Failure<Nothing>("connection failed.")

        return JSON.decodeFromString(con.decodeStream())
    }
Sorry if my explanation is a bit long but yeah this is my current problem, thanks in advance for the help.
g
Frankly, I would use
Unit
instead of
Nothing
. Because it's more idiomatic. While
Unit
represents "no return/output" ("it just did some work and there is no output of the work"),
Nothing
represents "just nothing".
Nothing
(shortly saying) means that you won't get the result by some reason. I.e.
fun foo(): Unit
means that there will be result but no output, whereas
fun bar(): Nothing
means that there even won't be any result of the execution. It's also confirmed by fact that the sources of all `Nothing`s are
throw
and (empty)
return
expressions. Also,
Unit
is reifiable.
t
This is a great explanation, thank you so much!
I actually didn't know the difference between Nothing and Unit but that really cleared it up
e
Nothing
is equivalent to
Never
in Swift and Rust (which also has the shortcut
!
), if that name helps