Super excited for this. If you haven't checked out the latest proposal, here's an example of what Option/Result box types might look like (obviously not ready for release, just an experiment):
> Viewing and/or sharing code snippets is not available in your country for legal reasons. This message might also appear if your country is misdetected. If you believe this is an error, please file an issue.
Shame as a species we can't even share information (literally bits on the wire) globally, even if tangible goods and movements are circumscribed by political borders.
Go's type system is actually expressive enough to ensure exhaustiveness, although it's non-obvious and syntactically heavy and impractical. I am working on a paper that will explore this.
> Each Unwrap() call needs two OK() calls? Letting Unwrap return OK would be better?
That would rather miss the point as you'd be converting the type-safe result to an unsafe version?
Go doesn't have pattern matching or any "structural" construct which would allow performing this in a single step, so the alternative would be to use HoFs and while Go has them they're quite verbose e.g.
func (o Option[T]) Then(then func(T)) {
if o.OK() {
then(*o.value)
}
}
a.Then(func (v int) { fmt.Printf("\tvalue = %d\n", v) })
which is… less than great.
An safe other option would be a method mapping to a slice of 0..1 element and you'd use a `for range` as an `if` but that seems way to clever, similar to Scala's comprehensions over everything which I rather dislike.
Also sadly the current proposal has no facilities for methods generic in their arguments independently from the subject, so no `Map` method.
Reading the specification (https://go.googlesource.com/proposal/+/refs/heads/master/des...) this flows from the type being declared generic, Go will (currently at least) require the receiver to be similarly generic, no specialisation, and no method constraints:
> Generic types can have methods. The receiver type of a method must declare the same number of type parameters as are declared in the receiver type's definition. They are declared without any constraint.
// Push adds a value to the end of a vector.
func (v *Vector[T]) Push(x T) { *v = append(*v, x) }
> The type parameters listed in a method declaration need not have the same names as the type parameters in the type declaration. In particular, if they are not used by the method, they can be _.
Because it can only be a type parameter. There is no specialization. (TBH I think that's a mistake because if prevents a solution to the Expression Problem.)
I don't think that's an issue, specialisation is a real edge case (e.g. Rust still doesn't have userland specialisation despite having always had generics) and it's easy to make mistakes with it (e.g. C++'s `vector<bool>` though it's probably less of an issue if you can only specialise functions).
That methods can't be parametric is still annoying though because it means utility methods can't have generic parameters unrelated to the subject e.g. can't define a map or fold method, because there's nowhere to put the output type, it has to be a free function instead.
But it's not like adding the generic spec thing between the subject and the method name would be a big issue so that can always be added later after the MVP has been exercised a bit.
A related "missing bit" which I'd guess they want more feedback before adding would be "conditional methods" aka methods which are only present if the generic types of the subject have a specific property (e.g. in Rust it's common for the generic container to be unbounded but for functions to be bounded on specific traits).
Adding it later is not impossible, but unfortunately is not that easy either. Ignoring the very high bar for changing Go in general, doing it this way has implementation consequences that would have to be undone. Also the spec change is not just a matter of adding more stuff, but it requires reformalization of the existing semantics because interfaces are already rank-2 types, you just can't see it yet. This feature interacts with interfaces.
It's very unfortunate thay didn't do this from the start. The original paper that introduced Go generics had this and used to to solve the Expression Problem.
No, Go doesn't have discriminated/tagged unions or valued-enumerations or whatever you want to call them, but generics let you hack them in without much trouble. Personally I'd take ADTs over generics any day, but it's not a dichotomy maybe we'll still get them some day.
I guess I'm understanding some of the concerns. It does make the code harder to understand. I wish they would use the angle brackets to match other languages.
https://go2goplay.golang.org/p/krvTH1_7lwX