Edit: I’m impressed generics aren’t a breaking change! I thought this changed Interface{} to Any as a breaking change
For the release announcement: https://news.ycombinator.com/item?id=29556646
So an unbounded type parameter is [T interface{}], or [T any] when using the shorter alias. It's a type alias / predeclared identifier defined in the universe scope:
type any = interface{}I never jumped the Go bandwagon because of the lack of generics. Can I now try Go?
The following article seems to say that the lack of other features can be frustrating (the lack of lambdas and the lack of the functional handling of collections seems problematic to me)
Also I wonder whether the language has a IDE support as good as IntelliJ with Java (safe function extraction, type-safe autocomplete)
Would the local gurus here please comment?
[the idea for me is to replace my tricky shell scripts with Go scripts.]
https://medium.com/webstep/a-java-developers-adventures-thro...
Go often works well for replacing shell scripts, even without generics.
Probably no. You still would be very disappointed. Go's take at writing and maintaining software often is pretty repugnant to people with a strong Java or JavaScript mindset. If missing user defined parametric polymorphism ("generics") was a reason to not even _try_ it you will be offended by by other things Go does in its particular way. Be it error handling, pattern matching, concurrency, mutability, etc. Basically if you try to write Java (or JavaScript) programs in Go you will suffer and hate Go. Same for C++/Rust aficionados. Go's newly added "generics" still come without "library support".
Jet Brains makes GoLand, which is about as good as they come. It should feel familiar if you're used to IntelliJ. https://www.jetbrains.com/go/
[]interface{}{1, 2.0, "hi"} -> []any{1, 2.0, "hi"}
Now that Go is going to have generics, all we need is sugar syntax for early return on error -- like more modern languages such as Rust and Zig have -- and Go may finally be pleasant to program in!An empty interface can represent any type because every type inherently implements an interface with no methods. And that's what Go is all about -- implicitly implementing interfaces.
If a newbie hops into Go and just starts using "any" I think they might assume it's a magic type that's at the base of everything, missing out on the fact that they're still taking advantage of interfaces.
It makes me a bit sad to read that. We all are on a journey to be become better developers every day. But things like that are like a distraction. They make you think you found a really cool and smart concept, but you actually didn't and it's essentially just a hack.
Not sure what the solution can be. But PL designers should be more clear about features that are just "hacks" and considered "bad" but necessary in practice due to certain constraints. Go's {} and nil-errorhandling are examples. Nulls (in any language) are another common example.
Let's see how this plays out.
There's a few other languages out there that work that way. The split is probably is probably 20/80. Though "popular" languages heavily learn towards Java-esque interfaces - with TypeScript and Go being the odd ones in that bunch.
Having lots of syntactic sugar works out OK for Haskell.
For example, in Haskell straight-line imperative looking code is an alias for some underlying callback hell.
The state of error handling in Go at the moment is embarrassing at best.
type Result[T] struct { ok: *T err: error }
Great, so how do you work with it?
* You can have a `ok()` getter that returns `*T`. Now you you need an `if x != nil`
* `isOk()` + `isErr()`
* `unwrap() T`, which panics on errors
* `split() (*T, err)` that splits into separate values, especially awkward since you both need `if err != nil` AND dereference the pointer
That API is more awkward then the status quo, and doesn't buy you any correctness guarantees because eventually you have to do an `if x := res.ok(); x != nil` or `x, err := res.split(); if err != nil {` anyway.
Pretty much the only convenience you gain are functions like `map()` or `unwrap_or`, but eventually you always have to take out the value and without being able to pattern match you can't get an API that improves correctness much.
(std::optional in C++ is a great example)
People makes it a big deal, in reality it's not.
Can you provide an example? What's wrong with `return err`? That's a very explicit early return on error, no magic or language features (= added complexity) needed.
The baseline is that constraints aren’t best expressed as interface literals in situ. Unlike exceptional use of ‘interface{}’, ‘any’ will be a more naturally invoked constraint.
Also, some of the uses of constraints rely on a unification involving an ‘any’ term that cancels out. Here, the use of ‘interface{}’ is not incorrect but maybe indirect.
func doSomething[X interface{}, Y Fooer[interface{}]](v X, src Y) error {
}
versus: func doSomething[X any, Y Fooer[any]](v X, src Y) error {
}
the signatures can get long pretty quickly when you have more than one type parameter. type any = interface{}
not work, if you felt that strongly?type Any interface{}
?
`type any interface{}` would declare a new type, while an alias is exactly another name for the same type.
type any = interface{}
That means they're interchangeable compared to defining a new type. type Any = interface{}
That is, it's an alias and casting is not necessary.That would get rid of the "panic: runtime error: invalid memory address or nil pointer dereference" errors.
https://wakatime.com/blog/48-go-desperately-needs-nil-safe-t...
… and pattern matching. Maybe just some extensions for `switch`.
… and one of the `try` proposals.
That having been said… I do appreciate that Go has gotten where it is today by being radically simple, and that a lot of extreme care needs to be done to add new features to the language. It’s hard to draw a firm line in the sand. I feel like all of these features would work great together, though; it’d enable Go to do something like `Result` in Rust with few language-level changes.
I even remain somewhat skeptical about generics, but I am hopeful.
> … and pattern matching. Maybe just some extensions for `switch`.
Go has type switches which are… ok. If it were possible to “close up” interfaces and type switches took that in account (match completeness) you’d be done about done, you would not have the structural / patterned unpacking but that’s probably less of a concern.
But that's already possible, just declare arguments and return values as values instead of references. I mean you'll get the zero value if you don't use those functions properly, but those won't cause nil pointer dereference errors.
I mean, it's a tradeoff between performance and developer competency. To be harsh, I think nil pointer dereferences are developer error, not a flaw in the language.
There is also a tutorial on generics: https://go.dev/doc/tutorial/generics
https://www.makeworld.space/2020/11/go_modules.html
Looking for a tutorial on generics myself.
The normie PL bar is rising, slowly but surely.
Is this a real command? If so, I’m very impressed. Is there any equivalent for c++ and other languages?
The combination of unambiguous syntax and consistently-formatted code results in rewrites producing meaningful diffs (most of the time).
[1]: https://pkg.go.dev/cmd/go#hdr-Update_packages_to_use_new_API...
[0] https://www.jetbrains.com/help/idea/structural-search-and-re...
func foo(x interface{String() string}) string {
return x.String()
}Same for an old Android phone with outdated Snapdragon 660 I use to test app performance bottlenecks. Except this one took 4 secs to load.
Oh, and maybe this goes against the Go ethos, but Python has a library called Sympy for Computer Algebra, and it's quite nice. It clearly relies on operator overloading.
I'm guessing this won't happen for a long time because operator overloading has a reputation (rightly or wrongly) for being abused. Oh well!
[edit]
More philosophical point: Overloading in programming started with mathematical operators, no? The motivation for having it as a language feature is very clear (if you know enough mathematics). What happened?
People have written programs in both of those areas using Fortran-IV which doesn't have overloading either.
I suppose I've fed the troll.
I also like that Go is fast. It appears that some Python code is being rewritten in Go to make it go faster. Python's slowness is a problem in both the areas I've mentioned, and I know the usual workarounds.
[1] Cornelius Diekmann, “Looping with Untyped Lambda Calculus in Python and Go,” Paged Out!, vol. 2, p. 22, Nov. 2019. https://pagedout.institute/ https://www.net.in.tum.de/fileadmin/bibtex/publications/pape...
If there is, I imagine it's not among the type of people who you'd want leading technical decisions at your company.
Also, application servers are cheap, persistent, fast and durable storage isn't, these won't be written in TS.
TL;DR: different problem domains, not important
You mean a reserved keyword? No, 'any' is not a keyword, it's an identifier (a predeclared identifier). The usual shadowing rules apply.
But having `any` as syntactic sugar for that concept is a good idea.
type fileOps []any // []T where T is (string | int64)
Go does not have neither generics nor union types. So people have to do this kind of thing :( I feel sorry for them.Reminds of Java 4 (15 years ago or something) where code was full of this crap:
List /* <String> */ values;
Map /* <String, Object> */ map;
Some devs spent a whole week doing nothing other than removing those commented out generic type declarations once Java finally got generics!It's really interesting you used those as your examples because that need was fully met in a type-safe way already, and other examples are actually much rarer to come by.
Trying to counter argue against an example by using the actual example, rather than the point the example is trying to convey, is a common, but quite dishonest debate strategy.
Fast-forwarding to today, could Co-pilot have saved them the trouble?
[0] https://www.jetbrains.com/help/idea/structural-search-and-re...
Oh good grief. There are 32,768 programming languages. People are free to pick the ones they want to use and nobody wants your pity.
for sum < 1000 { sum += sum }
while sum < 1000 {}
reads better (like English).Not a bad move, though. Most Go "Interface" things do tend to be "{}"