> This is clearly a key issue. I happen to think that contracts are > fairly clear for the reader: take your type argument and see if the > contract body works. I feel that everyone who knows Go will be able > to do that. But maybe that's just me.
For complicated contracts—and I mean even ones reduced by a tool to their minimum—that turns into a puzzle solving contest. For ones that aren't reduced, it's easy for them to be misleading, like: x % 5 == 0 I agree that it's something where eventually standardized practices and tooling would fill in the gaps to the extent that these issues would come up rarely. I'm mostly worried about the time between their introduction and the stabilization because it will be measured in years and remembered for longer. > Something like the convert example in the design draft would still > need contracts that are unlikely to be defined in the standard > library. In my draft proposal, I handled this like (type S, T interface{} | S(T)) which introduces two type parameters with no restrictions other than that values of T must be convertible to S. It's treated specially but it is somewhat special because it's a property between two types. It was the only such property I found necessary. > It's not necessary to support fields but I think it really is > necessary to support operators. I claim that, other than type safe > data structures, the number one generic function that people want to > write is Min (or Max). I don't think we can plausible add a generics > system to Go that doesn't permit writing a Min function. Hypothetically, if Go introduced generics where you couldn't write min/max but included min/max builtins, what's the next smallest example where operators are necessary? I'd argue that min and max are the only ones that would seriously be impacted. Every other example is large enough that any boilerplate to wrap methods would pale compared to the coding saved by being able to safely reuse a large chunk of code. I'd be happy with generics if I needed to sometimes write a little bit of code to do a few things but didn't have to write a tremendous amount of code to do most things. That seems like a good trade off, even if it's not necessarily a popular one. But you can't really write a generic min/max with the contracts proposal. You can write a min/max that operates on all the ordered types, sure. (The one in the proposal has a bug because it accepts float types but doesn't handle the special cases for floats. That can't be repaired because while you could assert to float32 or float64 you couldn't assert to type MyFloat float64. Though I'm sure there's some contract where you can specify < but not floats.) You could also write a min/max that operates on types with a Less method, like you could under the various just-interfaces schemes. But you can't write one that works on both. If there were operator overloading any type could have < and you could specify < in interfaces and then you could work on primitive and user types equally. But even then you still couldn't write a min/max that transparently works on time.Time since it has Before not Less. To unify those cases you need something like haskell-style typeclasses where you can say this type satisfies this contract using these methods/operators. Even ignoring that, the contracts proposal doesn't let you write a generic variadic min/max since there's no way to get the smallest/largest value of a type so you can't write func min(type T ordered)(ts ...T) T { min := LargestPossible(T) // not possible for _, t := range { if t < min { min = t } } return min } You could get around that with the signature (firstOne T, rest ...T) but there's a larger point about the necessity of knowing numeric limits and properties for writing that kind of generic code in there. One way around the asymmetry between operators and methods that doesn't introduce any issues like operator methods or any of that is to have a package that defines types like package basic // not the best name type Int int type Slice(type T) []T // and so on for all the primitive and basic composite types and give all of those methods like Less and At. You'd have to do int(min(basic.Int(x), basic.Int(y))) but at least you wouldn't have to write the trivial wrapper methods. Not especially pretty. -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.