Unit is the worst naming

It was explained before – Kotlin uses Unit so that functions are regular.

Lambdas that don’t return a value don’t need special handling versus lambdas that do. Since all functions return something (except the ones that don’t return at all i.e. Nothing :-)). Therefore we don’t need workarounds like the Java Consumer and the Java Function. In Kotlin, functions are not either Consumers or Functions – they are just Functions.

I agree the naming is not necessarily obvious, but other languages that support functional programming operate the same way. For example, Scala uses Unit as well.

As I was writing this, I thought – wait a second, it can’t be the case that Swift functions are not regular – and indeed, I was wrong earlier. Swift functions with no return value DO actually return something: the empty tuple (), which Swift simply aliases to Void:

typealias Void = ()

Try running this code:

func f1() {
  print("f1")
}

// a compiler warning, not an error!
let f = f1()

// prints `()`
print(f)

So that Swift code prints () which is not so different than your example code which prints kotlin.Unit.

So if you think the Swift behavior is ideal, now you know Swift operates almost exactly like Kotlin. All we would have left to haggle over is naming and compiler warning behavior. The Kotlin compiler could probably be modified to emit a warning in that situation just like Swift does. So this isn’t a fundamental language concern.

If you didn’t know this about Swift Void, then its a good example of why using a different name is a good idea – it forces you to learn and understand as opposed to proceeding unchecked with an incorrect assumption, as I believe we were both doing with Swift.

You said:

Blocking is not about heavy operations. It is a Thread that can’t do anything else because it is waiting for something. For example, the JVM Thread.sleep method blocks a Thread. In fact, a Thread that is doing heavy operations is not actually blocked, it is in a Runnable state.

Blocking simply means the thread is blocked and cannot move forward. This is standard terminology for Java threads. runBlocking is meant solely as a bridge from the world of threads to the world of coroutines. It is therefore doing exactly what it says – it is blocking the current thread while waiting for the coroutine to finish i.e. that thread is blocked and cannot do any other work.

Its natural to be a bit confused when encountering new language constructs, but once understood I don’t see how this isn’t reasonably developer-friendly?

Yep. I explained earlier why I think suspend was a better choice than async/await so I won’t rehash that. Its a valid point there is nothing in the code to indicate a suspension point (though IDEA shows it very clearly in the gutter). I haven’t found this to be a problem in practice.

You come from a Swift background? I come from a Java/Kotlin background and this is exactly what I think every time I use something new in Swift. Then after a while I learn how it works and think “yeah, that’s not too bad”. So mostly this is about language familiarity. But, I maintain that Kotlin by and large makes dev-friendly choices more often than not.

4 Likes