Unit is the worst naming

And this is exactly the point of the coroutines design. If you don’t use threading, coroutines, etc., just the classic code and you need to run one operation after another, then you do:

doSomething()
doSomethingElse()

If you use coroutines and you need to run one operation after another, then you do:

doSomething()
doSomethingElse()

How is this counter-intuitive and it would be more natural to use words like async/await to accomplish the same kind of behavior?

I see it exactly the opposite to you. From your description (I don’t know Swift), Swift focuses on what is happening inside the function, focuses on its implementation details, we need to consider if function is asynchronous or not and use it accordingly. Kotlin focuses on the fact that we called a function and we don’t even have to know if it is asynchronous or not - the code is exactly the same.

3 Likes

Completely agree with you. However, note the Swift design is actually pretty similar, though the async/await terminology is confusing. Adding the async key word to a function is just like marking a function with suspend – it indicates the function suspends/resumes (even the Swift docs describe it this way).

I’m not a Swift expert either, but I think the main difference is that in Swift you as a developer must mark a suspension point with await, OR assign the result to an async let variable which would be similar to using val deferred = async { … } in Kotlin. I’m not positive how async let plays with structured concurrency. I don’t think Swift’s structured concurrency story is as comprehensive as Kotlin’s – see this thread for example.

The Swift approach seems easier to understand for beginners because devs don’t need to worry about things like scopes when doing a basic async/async let, but harder to correctly program a larger application because devs would need to know when to opt out of the implicit behaviors.

2 Likes

Hey @Raman.Gupta I run onto this thread this morning.
It gives a good idea about the difficulty for understand the “suspending” terminology.
https://stackoverflow.com/questions/47871868/what-does-the-suspend-function-mean-in-a-kotlin-coroutine

You can find people on the Internet confused about pretty much any topic. Shall I search for similar posts about Swift async/await for you?

In the particular case you linked, the questioner is confused about whether the suspend modifier means the function suspends, or if it means the coroutine suspends. This indicates confusion about concepts more basic than coroutines, suspending functions, or async/await. The questioner does not appear to understand that every function in a program is run by threads – functions don’t run themselves somehow apart from threads/coroutines. The suspend is a modifier and it just tells us (and the compiler) something about the function just like Swift’s async modifier does.

The questioner could ask almost exactly the same question about what the Swift “async” modifier means because the Swift documentation statesAsynchronous code can be suspended and resumed later” (my emphasis).

This will likely be my last reply to you because you are not addressing any of the arguments made to you in previous posts. You just keep moving the goal posts, First you started with Unit, then you went on to suspend, and now you’re posting almost random SO’s. Unless you engage with the arguments presented, replying to you is a waste of time. My only consolation is that my posts may help one or two other readers.

1 Like

I didn’t answer your email because, if I said I understood your point of view oriented on the technical aspect, you don’t understand my point of view that I place on the educative (cognitive) aspect.

The thread I posted reflect the problem I exposed from the beginning.
You say that tone of guys can be “confused about pretty much any topic”. I say that confusion come essentially from inconsistence in semantic usage or knowingness. In a most of the case, an excess of complex words, followed by inappropriate usage of words.

Unit is a technical consequence, not a frontal understandable meaning, except for someone who knows the underlying technic. As a rule, you should limit the biases to have to know the background of something before to start to learn it. What a primary accessor understands with functions is that a function can return a result, or return nothing. The reason why very surely the vast majority of languages choose void — even though technically, in the gut is not so exact.

Suspend is a technical consequence, not a frontal understandable meaning for someone who start with the subject to run some stuffs, on the main, because he needs run some parallels stuffs, not to stuck his UI.
This is probably the reason why some languages preferred to use async/await.

Accessibility is all about my concern. Not the “absolute” truth that could / should / must be given by chosen terms.
Does a “word” help to understand the primary usage or not. If not, I, as UX and Cognitive Science lover, consider it’s an accessibility (and unnecessary) stop.

(PS: no, I’m not stuck in a ‘swifty’ vision)

You can’t hide the cognitive complexity for learners simply by using words that point to simpler concepts, if the simpler concepts lead the learner to the wrong understanding!

It was explained to you that it does not return nothing. Swift also does not return nothing, even though they define Void as a type alias. So perfect example: use of the word void reduced your cognitive load, but left you with the wrong understanding.

Another example of the same problem. It was explained to you that suspending functions do not run stuff in parallel. Your choice (and Swift’s choice) of using async/await reduced your cognitive load because they were familiar to you, but again, they left you with the wrong understanding.

1 Like

You SHOULD hide the complexity in order to allow the greater number of people to access easily every thing, in order to give them the possibility to improve their skills with the less of barriers. It’s an educative principle.

So on the side of education and accessibility even with all good technical justifications, Unit is a bad choice, and suspend remain discutable.

In the whole discussion about Unit, I still miss some good ideas or recommendations for alternative names or approaches. I personally hate Unit, and still I don’t see a better name. So at least for me discussing why Unit is bad isn’t very productive.

2 Likes

I agree with you that “why Unit is bad” can be counter productive. But sometime to understand the underlying of a “design” allows to understand what this “design” tries to solve.
The process of design is to understand exposed pains or frictions, or origines of solutions to figure out if we are addressing correctly the underlying pains or frictions or if on the contrary we are just facing forefront solutions which have been imposed by some “design processes lead by some considerations”.
When it turns to design a language or any library we are driven by rules of meaning in order to expose rapidly, the most intuitively as possible, what entities are, do, produce…
keywords, function name, param names, types… definitions are driven by that kind of rules.
You can take the rule to expose the most as possible the underlying mechs in the surface semantics, or you can take the one to be the more simple to give a larger access.
It’s true for code, for device, for book, for tech, for everything.
What is pretty true is that “named stuffs” must have an easy meaning, and make application/usage easy especially if they are in a high frequency usage.
It’s noticeable that () exists in other languages but does’t wear name for most.
What did lead the attribution of Unit for () is a very intellectual approach that shouldn’t rise the surface of “for everyone code”.
I practice different worlds in the code universe (I teach to engineers) it’s noticeable to meet some computer science namings (like factory, stateful, pattern…) in the documentation of Android SDK, things you’ll not find in the documentation of Apple SDK.

Like you I don’t like Unit, I would prefer they used Void (in the fact () is a 0 byte stuff, so it’s nothing) and for simpler users, it’s just meaning a function returning nothing and that it.

Try to explain to a newbie that a function that return nothing, in fact something you can’t use, is for him a total confusion, coming in the right line with all the mess he met when he study math functions that are so badly taught.

I understand @Raman who defends the idea to be “technically” true. But I defend the idea to be as accessible as possible, and let to the few specialists the opportunity to be confronted to the underlying mechs.

1 Like

While recommending this, do you account for the fact Java already provides Void, so while targeting Java we have two distinct Void types, meaning different things and used in different scenarios?

1 Like

I think in many case we could map Java “function no value returned” by Void and map the Void.Type with kind of java.VoidType. No?

1 Like

If you like Void instead of Until feel free to create a type alias to use in your own code. But I think it is more confusing with the concept of returning a void. As people keep telling you and you seem to ignore is that returning Unit does not mean not returning anything.

2 Likes

I would prefer Void as well, but I think it’s a bit late for that. Kotlin will probably have to stick to Unit unless you’re OK with breaking lots of existing code. That said, I have a project where I ran into exactly that naming collision, and I simply named my class Unyt. No big deal. I could also have used backticks, but that’s tedious to type.

1 Like

I totally agree with @lucolivier .

Yes, many FP languages (and category theory) use Unit, but obviously it’s not a good name for most engineers who not very familar with FP. IMO it’s also not accurate, because in theory any type which only have one value can be called “unit” type. So the name “Unit” does not show the real intention.

I don’t know why kotlin use “Unit” in the first place, especially Java already have “Void” (the Box type for void). Technically it’s just unit type (the only valid value is “null”), and it also can be used as generic param. IMO, it’s nothing wrong and it’s better to reuse java “Void”.

One possible confusion is “Void” and “Nothing”. In some FP languages (eg. Haskell) they use “Void” for empty type (aka. Nothing) not unit type. But I think most engineers don’t care about that.

BTW, someone in the discussion said Swift do not have “Nothing”. It’s wrong, Swift also have it, just name it “Never”. And, TypeScript also have “void” and “never” types, with the same names like Swift. I think both TypeScript and Swift have the right names, compare to kotlin.

PS. I recently involve in the developing of a new programming language. In the very beginning (before I join the team) this new language had void type like Java and can’t be used as generic param. The team fixed it but also renamed void to Unit. Last week we decide to go back to void and I’m very happy about that.

1 Like

I think this is a big difference, though. In Kotlin Unit is an object. You can assign Unit to a variable. But you can’t assign Void to a variable in Java; Void is an interface that is never instantiated. So idk how that would work if you tried to use Void in Kotlin… maybe there’d have to be an internal object called VoidImpl or something that implements the Void interface, and then all methods that currently return a Unit would instead return the VoidImpl?

2 Likes

Void is not an interface. This wouldn’t make too much sense as anyone could implement it and return it. It is a non-instantiable final class.

Kotlin is null-safe, so it can’t use the pattern known from Java. null is not a valid value for the Void type. It would have to be Void?. Kotlin could potentially alias Void to Java’s Void?, but what if someone calls toString or use reflection? We might get NPEs in such cases. I think Void as known from Java doesn’t fit the language design nicely. Also, it feels a little silly we have a nullable type, so a two-state variable, but in practice it can only hold a single state.

Maybe a Null type would be a better choice. It would allow only a single null value and it would be a subtype of every nullable type. Still, a Unit approach (whatever name we choose for it) seems more pragmatic.

3 Likes

Wow, I swear I remember looking at Void and seeing that it was an interface. I guess my memory is wrong in this case.

1 Like

We already have this: Nothing?. As you say, it’s a type with only a single value (null), and is a subtype of all nullable types.

Although its name is perhaps less immediately obvious as a null type, it’s more consistent with the rest of the type system. I guess you could easily add a typealias for Null if you wanted.

1 Like

We don’t actually expect to ever get to a point in the code where we get a value for Nothing. Nothing doesn’t have a valid value. For Unit / Null we return normally from a function, and there is a valid value for them, but the value is meaningless.

The type I mentioned is Nothing?, i.e. nullable Nothing — which is different from plain Nothing. Like all nullable types, null is a valid value for Nothing?; the difference is that it has no other valid values (because, as you say, Nothing is the bottom type with no values).

(I remember remarking hereabouts several years ago on the oddity of Kotlin having two one-valued types, Unit and Nothing?, and speculating on whether they could have been merged. I don’t think anyone else was interested, though.)

2 Likes