logoalt Hacker News

qcnguylast Sunday at 5:21 PM3 repliesview on HN

Weird the author finds it lovely and compares to Kotlin, but doesn't find Kotlin superior. Kotlin invested heavily in a really nice curly brace syntax. It is actually the nicest out there. In every point the author makes, it feels like Kotlin did it the same or better. For example:

1. Integer literals. "var a = 1" doesn't work, seems absurd. In Kotlin literals do have strong types, but coercion is allowed when defining variables so "var a = 1" works, and "var a: Long = 1" works even though you can write a literal long as 1L. This means you can write numbers to function parameters naturally.

2. Multi-line string literals. OK this is a neat idea, but what about copy/paste? In Kotlin you can just write """ .. """.trimIndent() and then copy paste some arbitrary text into the string, the indent will be removed for you. The IDE will also help with this by adding | characters which looks more natural than \\ and can be removed using .trimMargin(), only downside is the trimming is done at runtime but that could easily be fixed without changing the language.

3. Record literals. This syntax is called lovely because it's designed for grep, a properly funded language like Kotlin just uses named kwargs to constructors which is more natural. There's no need to design the syntax for grep because Kotlin is intended to be used with a good IDE that can answer this query instantly and precisely.

4. Function syntax. "fn foo(a: i32) i32 {}" seems weird. If the thing that has a type and the type are normally separated by a : then why not here? Kotlin does "fun foo(a: Int): Int {}" which is more consistent.

5. Locals. Agree with author that Kotlin nails it.

6. Not using && or ||, ok this one Zig wins, the Zig way is more consistent and reads better. Kotlin does have `and` and `or` as infix operator functions, but they are for the bitwise operations :(

7. Explicit returns. Kotlin supports blocks that return values and also doesn't need semicolons, so not quite sure what the tradeoff here is supposed to be about.

8. Loops being expressions is kinda cool but the Kotlin equivalent of his example is much easier to read still: "val thing = collection.first { it.foo > bar }". It compiles to a for loop due to the function inlining.

9. Generics. Zig's way seems primitive and unnecessarily complex. In Kotlin it is common to let the compiler infer generics based on all available information, so you can just write "someMethod(emptyList())" and emptyList<T>() infers to the correct type based on what someMethod expects.

Overall Zig looks like a lot of modern languages, where they are started as a hobby or side project of some guy and so the language is designed around whatever makes implementing the compiler most convenient. Kotlin is unusual because it doesn't do that. It was well funded from the start, so the syntax is designed first and foremost to be as English-like and convenient as possible without leaving the basic realm of ordinary curly-brace functions-and-oop style languages. It manages to be highly expressive and convenient without the syntax feeling overly complex or hard to learn.


Replies

lenkitelast Sunday at 5:58 PM

> There's no need to design the syntax for grep because Kotlin is intended to be used with a good IDE that can answer this query instantly and precisely.

On large projects its still cheaper and faster to grep from the CLI than to use Intellij IDE search. Esp if you wish to restrict search to subsets of dirs.

Command-line greppability is a serious use case.

Zig is also 5-10x faster to compile than Kotlin.

On function syntax, I agree with you. It was a mistake not to use fn:ReturnType. It has destroyed future lambdas.

show 1 reply
johnisgoodlast Sunday at 5:36 PM

It is not just syntax that matters. For one I dislike JVM-based languages. I still write it sometimes for work.

show 1 reply
Tmpodlast Monday at 11:20 AM

> only downside is the trimming is done at runtime but that could easily be fixed without changing the language.

trimMargin and trimIndent (as well as other operations like concatenation) actually get handled at compile time if the string isn't interpolated.