I sometimes use wrappers around functions for thin...
# getting-started
l
I sometimes use wrappers around functions for things like handling common errors or setting up coroutines like below
Copy code
fun foo(x: Int) = myWrapper {
    doSomething();
}
where the wrapper function has a signature like
fun <T> myWrapper(() -> T): T
This works well for most cases except where I want foo to return Unit and doSomething() has a return type. In this case, I have to change the sample to
Copy code
fun foo(x: Int) = myWrapper {
    doSomething();
    Unit //return Unit
}
Is there a way to tell the compiler that if the function foo has a return type of Unit, it should ignore the value returned by doSomething(), and treat it like a normal statement, similar to if I didn’t have my wrapper?
e
Copy code
fun foo(): Unit = myWrapper { doSomething() }
fun foo() = myWrapper<Unit> { doSomething() }
either one will work
l
I tried the first already, and I get the compiler error
Copy code
Type mismatch.
Required:
Unit
Found:
Int
Where ‘Int’ is the return type of doSomething.
The second seems to work well. I’ll swap my definitions to match.
e
hmm type inference should be doing that… oh well
of course
Copy code
fun foo() {
    myWrapper { doSomething() }
}
is also possible
l
I assumed type inference would handle this as well. I also notice that if myWrapper returns T?, then it doesn’t work either, as I get
Copy code
Type mismatch.
Required:
Unit
Found:
Unit?
Unit?
doesn’t have any real meaning, does it?
e
sure it does, Unit is a real object type
l
I suppose Unit is an object defined in the stdlib, so it has a Unit? counterpart. I’m not entirely sure where it would be useful. I guess it makes sense to be consistent, but it would be nice if Unit were to get some special treatment in type inference.
It’s not the end of the world to add a
?: Unit
to the end of the wrapper definition. The main use I have for wrapper functions like this is converting Kotlin/Native exceptions to JVM exceptions using JNI. My JNI methods are all wrapped in a
handleException(block: () -> T): T
that will call
block
and catch some recognized exceptions, then instantiate the JVM equivalent and ask the JVM to throw it. I use the fun
foo() = handleException ...
to make it clear to the developer that handling exceptions isn’t a fundamental part of the job of foo, but something it does for correctness. I’ve always liked Kotlin’s syntax for this, especially with things like withContext(Dispatcher).
e
going into type theory for a bit,
Nothing
is the bottom type,
Unit
is the unit type, and
?
is
| null
. so of course
Nothing?
and
Unit?
have meanings: the former is only inhabited by the value
null
(and
), the latter is inhabited by
Unit
and
null
(and
)
y
Does bottom really exist in Kotlin as a value? Obviously
Nothing
is the bottom type (i.e.
) but I wouldn't necessarily say that
is an inhabitant of
Nothing
. This is different from Haskell having bottoms as a value because Haskell is lazy and so
is really a
() -> Nothing
e
calling
a "value" is questionable even in Haskell
and we're just talking about types here; it doesn't matter whether it's a lazy thunk or not at execution time
anyhow, I would argue that bottom doesn't "exist" as a value in either language, but it is something that the type system - in both languages - has to know about
💯 1
👆 1