Hacker News new | past | comments | ask | show | jobs | submit login

You have to click through to read the assignability rules. A very short summary is that people often create new types based on core types. For example:

   type Name string
Now you can define methods on Name:

   func (n Name) Foo() { ... }
   ...
   x := Name("Me")
   x.Foo()
But, you can't use Name and string interchangeably:

   func StringFoo(x string) { ... }
   StringFoo(Name("Me")) // does not compile
In the case of generics, maybe you want to write a function that can handle any string:

   func Bar[T string](x T) { ... }
   Bar(Name("Me"))
   Bar("Me")
This doesn't compile, because Name isn't assignable to string. The fix is to declare the type parameter as [T ~string]. (The compile error suggests this, in fact. You can also write string(Name("Me")) but if T were being used as the type of the return value, the returned value would be type string, not type Name.)

In the case of slices, it can be more complicated. These types all seem similar, but aren't the same:

  []string
  []Name
  type StringSlice []string
  type NameSlice []Name
The idea of the article is figuring out how to write a generic type signature that would accept any of these and return the right type.

Finally, you can rename types and use them interchangeably if you don't want the "safety" of making a new type:

  type Name = string
Now you can't write methods on Name, but you can use Name and string interchangably. (This, incidentally, is how "any" works. The package builtin contains "type any = interface{}".)

If the complaint about syntax is not using <T type> to denote type parameters like Java and C++, [] simplifies the parser. You can read the original generics proposal for all the details.




Awesome explanation!


All that instead of type classes eh?


Indeed. Pains me to see what they are doing while not learning from existing and well established language patterns.

I understand that Go wants (or wanted) to stay "simple" but now it seems to become the worst of two worlds: it's neither simple anymore but also doesn't benefit from high level language features like typeclasses because it's too late to add them now.


It's more similar to semantic subtyping as a set interpretation of some types. That avoids having different constructs for similar things.

Personally I find this elegant.


Go has type classes, they're called interfaces


Not the same, because with an interface, the methods defined for the struct must match the interface.

With type classes you can bridge that gap because the implementation of the struct for a specific type class can be defined anywhere.


> [] simplifies the parser

Strong PHP vibes. They also went for weird syntaxes that don't exist or rarely exist in other languages to simplify the parser.

It's 2023. How is parsing anything is a problem?


Go 1.18 had to run programs written for Go 1.17. What if this is your program:

    a, b = w < x, y > (z)
Is that "a, b = w[x, y](z)" (call function w of with type parameters x and y against z), or is it "a = w < x; b = w > (z)" (assign true to a if w is less than x, ...).

With type information, this is possible to disambiguate, but the goal of the parser is to not require type information. Remember, now if you want correct syntax highlighting your editor has to have the type information, but you haven't typed that in yet!

As always, I think they made the right choice here.


> With type information, this is possible to disambiguate, but the goal of the parser is to not require type information.

Why?

It looks like a pretense at purity for the sake of purity.


Do you want to parsing your language to require implementing the typechecker and using shotgun heuristics, all so you can use <> instead of []? Compiler writers die for your sins in code. Let them do things that can drastically simplify things everywhere, instead of suggesting that they're intellectually jerking themselves off. Not that they're immune to that.

EDIT: Apologies, after a bit I realized the above is a bad comment.

Separation of concerns is a common pattern in programming. It allows for things to be testable and changes to be more localized. This is an example of that.


Separating parsing from semantic analysis simplifies the parser considerably.

If one of Go's aims was to make different trade-offs than [C++][1] did, then the choice not to use "<" as a grouping operator was a good one.

[1]: https://youtu.be/WfIr7lKT4Sk?t=204


lots of things in Go are very annoying, but this isn't one of them. being able to parse the language without type information makes parsing way easier and faster, which you definitely care about in at least one case - syntax highlighting in your editor.


> It looks like a pretense at purity for the sake of purity.

if you go (ah!) far enough on the other direction, you end up with 'template typename' soup.


So you don't have to wait as long for obvious errors. Anywhere near as long, like a couple orders of magnitude in many cases - milliseconds vs minutes.

Allowing ambiguity isn't just a style decision, it pushes error detection later, where you have enough info that it's no longer ambiguous.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: