tl;dr Was elegance a language design goal? What does that concept mean in Kotlin?
When I first looked at Kotlin a couple of years ago, I was starting with a lot of enthusiasm because I heard a lot of people praising the language.
When I actually started coding however, very soon I felt disappointed and ultimately stopped my journey to Kotlin.
The reason for that mostly was that for me Kotlin lacked in elegance and orthogonality.
It felt like there were too many disparate concepts and things that worked in one context did not work in another and there were too many special cases.
I really don’t want to bash Kotlin and recently I have started to use Kotlin for real (as a replacement for Java in the backend).
Still, I am curious what others feels about it or what the language designers think about elegance.
(For context: To me the most elegant programming languages I have used so far are Smalltalk and Scheme, which are admittedly not in widespread usage.)
Examples for things that itch me in Kotlin:
- Extension functions are nice, but mostly syntactic sugar.
- You have to explicitly import them.
- They are not virtual. So a specialized version for, say, LinkedHashMap is useless unless every variable is declared with that static type.
- Destructuring feels like a clutch to me with these generated componentX() methods. Why can’t it work based on names?
Imagine, I start out with
data class Contact(val firstName: String, val lastName: String)
val (firstName, lastName) = contactsomeplace else.
Now somebody adds a middle name:
data class Contact(val firstName: String, val middleName: String, val lastName: String).
val (firstName, lastName) = contactis silently broken and lastName now contains a middle name.
- The business around inline/noinline/crossinline/@PublishedAPI/reified and all the special cases around it is very confusing
I wish the compiler could decide itself where inlining makes sense and all features would “just work”.
- A very specific case: Why is the syntax for open/closed ranges so different: “for(x in 0…10)” versus “for(x in 0 until 10)”
- I would have preferred literals for lists and maps (like groovy’s [red: ‘0xFFf0000’, green: ‘0x00FF00’].
Constructing maps by first constructing a lot of Pairs and then calling a function is ok-ish, but doesn’t jibe with my sense of nice code.
- Kotlin’s Java compatibility is hailed in one of the very first sentences in every statement about Kotlin.
In practice, it requires to be careful and heavily annotate your APIs. That’s ok, but clearly a case where my expectations were higher than reality.
I guess a lot of this comes down to restrictions of the JVM itself or of the design goal “Java compatibility”.
To me, it feels like Kotlin values pragmatism above all and then applies a lot of band-aids and make-up for the resulting pain points.
(Sorry, this came out harsher than intended.)
Still, just out of curiosity:
How much were elegance and orthogonality a design goal?
And how do the language designers understand “elegance”? (Maybe their take on the concept is just very different from mine.)