As it's clear now that Ian wants to stick with 'full-blooded' contracts if it can be made to work, I've been trying to think of ways to make them easier to work with and to solve some of the issues they currently have.
Reading through the draft for the umpteenth time, one point that particularly struck me was that expressions such as: 1. ' t == t ' implies that both == and != are valid operations i.e. type is comparable. 2 ' t * t ' implies both * and *= are valid. 3. ' t < t ' implies that <, >, <=, >= , == and != are all valid i.e. type is ordered. Suppose this idea were taken to its logical conclusion. So in the case of #2 the compiler could further imply that it must be dealing with an integer, floating point or complex type (as only those types support the multiplication operator) and that consequently ALL the operations, conversions, assignments etc. which those types had in common could be used by a generic function/type that was constrained by a contract containing that expression. Similarly, #3 would tell the compiler that it must be dealing with an integer, floating point or string type as only those types are ordered. It's easy to think of a number of other simple expressions where the compiler could imply the allowable types: 4. ' t % t ' implies any integer type. 5. ' 1 << t ' implies an unsigned integer type. 6. ' -1 ^ t ' implies a signed integer type. 7. ' t == 1.1 ' implies a floating point or complex type. 8. ' imag(t) ' implies a complex type. 9. ' !a ' implies a boolean type. 10. ' t == "" ' implies a string type. 11. ' []byte(a) ' implies a string type or byte slice. 12. ' []rune(a) ' implies a string type or rune slice. 13. ' a + a ' implies an integer, floating point, complex or string type. Now let's further suppose that the standard library contained a contracts package (with a nice short name such as 'ct') containing contracts for each of these expressions. Let's give them some shortish names such as (in the same order): Eq, Num, Ord, Int, Uns, Sgnd, Float, Cmplx, Bool, Str, Bytes, Runes, Add So, for the first one, the actual code would be: contract Eq(t T) { t == t } Of course, as the code is not going to be executed, all that matters is that these expressions survive the type checker for the actual type used. The advantage of doing something like this is that where you only need a single type parameter and are happy to constrain it to one of these 'type-classes', you could do so straight 'out of the box' with a contract such as ct.Int, ct.Str or whatever. I suspect that this would cover a large percentage of use cases in practice and so would be a worthwhile feature. It might also satisfy those of us who favored a 'type-class' based solution, particularly as it doesn't require any more built-ins or other syntactic overhead compared to the original proposal. It's giving the compiler more to do in one way but less to do in another as it should solve nearly all operator/conversion problems without further ado. It should also solve the problems we currently have with untyped constants. For more complicated cases, the full power of user defined contracts would still be available. Does anyone else think there's any mileage in this idea or am I just whistling in the dark? Alan -- 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.