Hacker News new | ask | show | jobs
by twblalock 2190 days ago
On the <> syntax, why not improve the parser? Every language that uses <> for generics has a parser that is able to distinguish between generics and the "less than" operator, and it seems odd that Go developers think it can't be done efficiently.
6 comments

C++ and Rust require extra disambiguating syntax in some contexts (C++ the `foo.template bar<T>()` syntax, Rust the "superfish operator" `foo.bar::<T>()`. Java works around the problem by awkwardly putting the generic argument list in front of the method name (`foo.<T>bar()`). I don't know about C#.
C# is `foo.bar<T>()`, I’m not sure what compromises that had to make for that to work but from an end-user perspective it works well.
They parse it one way, and if they figure out the other parse option was right, they go back and fix the parse tree.

Basically, unlimited look-ahead.

Is it somehow a problem?
(teeny tiny note: turbofish, not superfish)
Oops :D
Using [] is the optimal choice for languages in general, but they can't even use that because they blew away that syntax for indexing.
Scala uses [] for generics and () for indexing, which sort of makes sense given that in the end arrays are just functions.
So are the uninstantiated generic types ;-)
Go developers like to claim that the reason the Go compiler is fast is because it's "simple to parse". Unfortunately this doesn't make a lot of sense as parsing is typically only 1-5% of the total compile time.
It's not only about the main compiler. Go has tons of third-party tools (linters mainly) that can parse go code, because it's so easy to write one. Most of them wouldn't exist if parsing was a PITA.
Those almost universally use the "ast" package provided by the stdlib.
It is not a question of "Improve" but a question of dealing with tradeoffs. The Go parser is built so that at every stage it is totally unambiguous what the parser has to do.

This reduces the amount of state that the parser has to carry around and makes the error messages for syntax errors easier to generate.

Languages that use <>'s for generics have to look at a larger amount of the code when parsing to work out what to do.

In my opinion, the new design doc clearly characterizes this as a design goal of the parser, rather than a hard constraint that cannot be resolved.

"Resolving that requires effectively unbounded lookahead. In general we strive to keep the Go parser simple."

It's totally fair to question the tradeoff - should having a simple parser outweigh the potential ergonomic benefit of <>? I don't know. The forum for this is probably the golang-nuts group.

The design doc doesn't say "simple", it says "efficient".

I think "simpler" would have been a stronger argument. While using <> would make the parser more complex, I have a hard time seeing that making a meaningful performance difference in a compilation context. Maybe if you're parsing a lot of Go without actually compiling it, but that doesn't seem like a use case to optimize for.

It's all a matter of where you accept the complexity - in the compiler, in the language, or in the downstream applications. In my view it's an obvious choice to choose a more complicated compiler on exchange for simpler downstream applications...
The main reason is probably that by omitting <> for generics makes the symbol table unnecessary as part of the compilation stage. Go and D are the two modern languages that are avoiding symbol table like a plague for faster compilation time, i.e. the code should be parseabled without having to look things up in a symbol table .
The golang approach has been to dumb down the parser, at the expense of making it more complex for users.
there is no complexity tradeoff for users here.
Angle brackets are easier to parse for humans.