package main
import (
"fmt"
)
func Id[T any] (a T) T{
return a
}
type Stack[T any] struct {
items []T
}
type Num interface {
type int, int16, int32
}
func add3[T Num](a T, b T, c T) T {
return a + b + c
}
type LinkedList[T any] struct {
value T
next *LinkedList[T]
}
func (oldNode *LinkedList[T]) prepend(value T) *LinkedList[T] {
return &LinkedList[T]{value, oldNode}
}
func tail[T any] (value T) *LinkedList[T] {
return &LinkedList[T]{value, nil}
}
func traverse[T any](ll *LinkedList[T]) {
if ll == nil {
return
}
fmt.Println(ll.value)
traverse(ll.next)
}
func main() {
node := tail(5).prepend(6).prepend(7)
traverse(node)
}
https://go2goplay.golang.org/p/9cpHFGwuZmAI read lists like these, try to understand what the complaint is and then... I realize that I just don't care. There have been two or three occasions in my career that I thought "Man, it would be nice if I could use some generics now", but other than that: I don't give a fuck.
Go is simple enough that I can do whatever I want with it, without holding me back. It is simple enough that I can understand what my colleagues try to do without much effort. It may miss some convenient short cuts, but it is trivial to implement them yourself on the spot.
If it feels therapeutic to write down you annoyances, by all means go ahead. Let it out and get some peace of mind. Other than that: stop whining and just go build something useful with whatever language you prefer.
It's good enough at replacing Python, Ruby or server-side JS. That's enough to make it quite popular.
Yes, though lots of pretty awful things are popular. Eg PHP.
As for Oberon, while I enjoyed it, my real fun was with Active Oberon.
Choose Rust and C++ for building your next OS, but Go is great when I need to build a web service that's fast enough and hire a team that may not know the language walking in the door but can be productive quickly.
https://www.f-secure.com/en/consulting/foundry/usb-armory
https://labs.f-secure.com/blog/tamago/
> Our work focuses in supporting free standing Go applications that can be coded as usual, while running on bare metal hardware and without an underlying OS.
For example, I spent a while staring at assert_eq! statements in Rust docs wondering if an array reference is redundant, like this:
assert_eq!(args, &["first", "second"]);
Can I just write: assert_eq!(args, ["first", "second"]);
Yes, I can. But wait, why can I compare these things at all, with or without taking a reference? Because the equality operator == is overloaded to be able to compare args (in this case it's a Vector of OS-specific string types) against this local array of constant strings. And clearly there's no way for the compiler to just magically "know" how to compare those somehow, the standard library explicitly tells it how to do so with an overload (by implementing the trait PartialEq)But it made intuitive sense that you can compare them, I only wondered how it was done after I started specifically investigating this code. At a glance it made sense, and it actually does what I expected.
In contrast overloading is silly when it invents a new meaning for the operator. C++ gets a (rightful in my opinion) kicking here for streams, but I can also see an argument for the same claim about using + for string concatenation.
Restated: If I see a = b + c in a program, I am OK with a, b and c all really being some complicated object and not just numbers, just so long as intuitively you can add the a object and the b object together and that is in fact what this code does. If that makes no sense, or it doesn't do that, then you shouldn't have overloaded the operator.
Have a look at how eg Haskell deals with operators:
- You can define your own, so you don't need to re-use bit-shifting for IO. And in fact, you wouldn't be able to do so.
- There's also specific kind of overloading, so that '+' can work with different types. But eg you couldn't turn bit-shifting '<<' into an IO operator.
The rules for shadowing of operators are the same as the rules for shadowing any other function or variable name.
In fact, operators are just a weird syntax to write binary functions in Haskell. Otherwise they behave exactly the same.
Whether to use operators or functions with 'normal' names is then only a stylistic question, and a library can offer both styles to its users. (And you can retrofit the style of an existing library without having to have access to the library.)
The author does not seem to be aware that generics are coming in Go 1.18.
> Language Extensibility
Go was carefully designed to disallow this kind of extensibility. The point is that operators and other language constructs like `for ... range` always can be trusted and have a known cost. The author basically lists a pro as a con.
Person A: “go lacks feature X!”
Person B: “that’s what makes it so simple!”
And round and round it goes...
Flagged, here's some previous discussion: https://news.ycombinator.com/from?site=yager.io