
A Go contract design combining the strong points of official draft v1 and v2 - dotaheor
https://github.com/dotaheor/unify-Go-builtin-and-custom-generics/blob/master/contracts.md
======
hacknat
That’s a lot of new, effectively, keywords that you’re introducing. I don’t
know if that’s a bad or a good thing, but I suspect the community will have a
hard time with it. Otherwise this is a creative solution.

~~~
mbnull
It uses effectively only the one keyword assure. The constraints look like
fields on the type variables, which have an ambiguity with package private
method expressions with the same name.

~~~
dotaheor
The constraint expressions are expected to be used in generic declaration body
scopes instead of top package scopes. For example:
[https://github.com/dotaheor/unify-Go-builtin-and-custom-
gene...](https://github.com/dotaheor/unify-Go-builtin-and-custom-
generics#contracts), so I think the ambiguity should not happen.

------
jchw
I would love to see something along these lines in Go. It would probably not
end the abject negative reactions people have to the language as I suspect
those are not actually about _what_ it lacks, but it _would_ solve some
practical problems.

Metaprogramming is the root of much complexity in programming, but the main
alternative is reflection. I suspect that with sufficiently advanced
metaprogramming reflection is essentially never needed, but you end up with
other costs.

In Rust you might find yourself deriving nearly every struct with a laundry
list of traits. This is a cool feature, but I think the equivalent situation
in Go is worth considering. Go doesn't have traits or macros, but it does have
reflection. In effect, in Rust you can choose what is generated off of your
structs, whereas in Go you get a baseline amount of generated information and
you choose what to do with it at runtime.

Despite being undoubtably less efficient at runtime, it has its advantages.
You don’t have to think about deriving Debug, for example, because there’s
enough reflection information to do the needful at runtime instead. In Rust
you may pay more executable space per struct in some cases due to having to
generate lots of bits of code, whereas in Go you end up with a lot of little
bits because each struct generates some data.

The important thing to think about here is that these approaches are actually
not so different. They shift costs around differently, but they ultimately
accomplish similar things. I think inherently the Rust approach feels much
more powerful, and I think that’s a fair assessment, but the Go approach is
flexible. The same struct metadata can print debug information, and not only
that, it can do so in multiple formats. It can be used to serialize and
deserialize data like JSON. I maintain a small library called Restruct that
implements binary serialization a la Kaitai Struct that uses reflection.

Not having generics has been a huge advantage and disadvantage of Go from the
beginning. Generics really do carry a lot of implications. On a sliding scale
of generating interface implementations from structural information at
compiletime to purely reflection based strategies, I think there is a sweet
spot.

My knee jerk reaction to contracts in Go was that it sucked. It seemed like a
very weak implementation of metaprogramming. However, I’ve come around to
thinking it might be the way to go.

Having advanced templates would be useful too, but they would have drastic
implications as well. What I like about contracts is they feel self contained.
It feels like everything else around the contracts usages is fairly normal and
it won’t have a strong impact on how Go is written today.

So while it won’t make a lot of people happy, it will probably help the day-
to-day Go programmer a bit, by providing the ability, finally, to generalize
functions. I’d argue there are rarely many circumstances where this is really
needed in day to day Go programming, and therefore this fairly minimal
approach shall serve the language well.

I think the future of Go and how it fits in with other modern programming
languages will be firmly cemented by which approaches are chosen to solve
common Go problems in Go 2 and 3, and this is certainly a big one. If you feel
unsatisfied by this, I think there is still room for more new programming
language research, and highly recommend people try languages like Zig, Nim and
of course Rust. Go may not be your thing or maybe not suitable for your use
cases, and I suspect its possible it never will be suitable for all use cases
after all. The same can be said about all programming languages for the
foreseeable future.

Regarding this particular draft, my only real input is that I dislike the
assure syntax for some reason. It would also be great to avoid new keywords if
possible, though I have no idea how you could avoid that here.

------
ilovecaching
I’m a C programmer, and I don’t really see what adding this additional
complexity will really bring to the language. I always think of C as half
typed. I get all the benefits of static typing where it makes sense, but I’m
also not afraid to do some casts and throw around some void pointers. Go has
it so much better with the underlying type attached to the interface.

