Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

It has tuples, local type inference, for loops on ranges, and anonymous functions/lambdas (which act as closures/"capture" scope). Hardly "almost none of these features".


Go doesn't have tuples (multiple return isn't that). This leaves us with local type inference, for loops on ranges, and anonymous functions/lambdas.

The parent also mentions: binary literals, raw string literals, uniform Initialization, standard algorithms like map, filter and any, and parameter packing. All of which Go doesn't have.

Plus, Go range loops are constrained to built-in types (slices, channels, etc.), unlike C++/Python where you can implement begin()/end() or the iterator protocol respectively and get it for any type.

So, from 10 things mentioned, whereas C++ and Python share ALL of them, Go only has 2 of them and sort of has one more (the range-for).

I'd stick with: "almost none of these features".


Go doesn't even have local type inference: http://ideone.com/RQzz7E. Contrast with a language that actually does: http://ideone.com/LtN1vQ. Type inference, even the local kind, means figuring out the types of variables from how they're used, not just from how they're initialized.


That's a completely arbitrary definition, and it is wrong. Type inference limited to the initialization point is still type inference, and actually most languages before Rust and Swift that have local type inference (C#, D, C++11) are limited to type inference at the declaration/initialization point.


> That's a completely arbitrary definition, and it is wrong.

The definition is very simple - the inference engine must use nontrivial inference rules to reconstruct the types. The rule “given P then P” alone doesn't quite cut it, which means that ”given that 0 is an int, then something that's initialized to 0 is an int“ also doesn't quite cut it. Calling what Go, C# and C++11 have “type inference” is akin to calling Python a statically typed language because it has a trivial type system with exactly one static type.

> actually most languages before Rust and Swift that have local type inference (C#, D, C++11) are limited to type inference at the declaration/initialization point.

Then they just have unidirectional type propagation - which is perfectly fine, just not type inference.


> The definition is very simple - the inference engine must use nontrivial inference rules to reconstruct the types.

Where exactly is this rule coming from ? What is the source of your definition ? And if it is the authoritative definition, why don't you go rewrite the wikipedia page, which is then wrong ? https://en.wikipedia.org/wiki/Type_inference

> The rule “given P then P” alone doesn't quite cut it

"Doesn't quite cut it" sounds like a very precise and scientific definition ! Also your categorization of C# is wrong, even by your own definition, because of function types inference and of subtyping, which makes the algorithm non trivial.

> Then they just have unidirectional type propagation - which is perfectly fine, just not type inference.

Again:

1. This is wrong, even by your own definition. You can have local type inference limited to the initialization point, and have non trivial resolution rules. See this paper by Benjamin Pierce for an example : http://www.cis.upenn.edu/~bcpierce/papers/lti-toplas.pdf

2. Where is this definition even coming from ? In my book, unidirectional type propagation is a form of type inference, and it quite logically follows: The type is inferred. The fact that you chose to draw a line, say, to flow sensitive inference (in the case of Rust and Swift) or to global unification style inference (ala ML) is a completely arbitrary definition, and one that I have to this day never encountered. Indeed, I can't find any online resource that agrees with you. Most language documentations, including C#, C++ and Go, call this type inference. Most researchers call any mechanism where a language infers the type, type inference, even the mechanism that allows you to call generic without specifying the type of the instantiation, as in this paper : https://www.researchgate.net/profile/Erik_Meijer/publication...

I have absolutely never encountered any definition of type inference which draws this line, and for good reasons, because it doesn't make any sense.


You are right about C#: The type of `x => x + 1` can't be said to be anything other than "inferred". I stand corrected.

But I disagree with the rest of your post. From the point of view of type inference, what matters is the nature of the type constraints that the type checking algorithm generates:

(0) Traditional type checking: All type constraints are of the form “T1 = T2”, where both “T1” and “T2” are closed type expressions. There is nothing to infer.

(1) Type propagation: All type constraints are of the form “X = T”, where “X” is a type variable and “T” is a closed type expression. Again, there is nothing to infer, but we might need to propagate “T” between places. Say, from the RHS to the LHS of a variable initialization.

(2) Type inference: Type constraints are arbitrary type expressions, which must be solved using a unification algorithm.

As for why type propagation doesn't count as type inference: http://lambda-the-ultimate.org/node/4771#comment-75771


Go has raw string literals.


Go doesn't have local type inference: http://ideone.com/RQzz7E. This is local type inference: http://ideone.com/LtN1vQ.

And it also doesn't have tuples: you can't store tuples in variables or larger data structures, pass them as function arguments, etc.


Go doesn't have tuples.

Go doesn't have local type inference

For loops on ranges are limited to Go built-in types, you can't create your own iterators.

So yes, almost none of these features are available in Go.


I'm new to Go- but I don't think it has tuples in the python sense[1]. Happy to be corrected here if there's a broader definition you're referring to.

I do wish it had support for slice unpacking like it does for return values. The assignment from returns or ranges is one of the things I really ejoy.

Edit: [1] I'll clarify that I define that as an immutable, indexable data structure that you can unpack in to multiple assignments.


It doesn't have "true tuples" but you can do multiple returns in a tuple-like way and there is syntax for unpacking it. While a pair can't be stored in a single variable, you can just manually unpack and repack them for a similar effect to what tuples can do. For the record, most languages don't have indexable tuples as far as I'm aware and make you unpack them with some form of pattern matching.


> For the record, most languages don't have indexable tuples as far as I'm aware

Most languages with tuples have indexable tuples either via language syntax or library functions. (For example, OCaml practically does, with fst and snd.)

> It doesn't have "true tuples" but you can do multiple returns in a tuple-like way and there is syntax for unpacking it.

There's a large difference between having multiple return values and having first-class tuple values.


Haskell/OCaml style "fst" and "snd" functions can't index arbitrary tuples (they only work on 2-tuples/pairs): http://i.imgur.com/PbhNxmu.png.




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

Search: