On Fri, Aug 2, 2019 at 6:55 PM 'Axel Wagner' via golang-nuts < golang-nuts@googlegroups.com> wrote:
> > contract Comparable(T) { > T comparable, Equal(T) bool > } > Wait, does this work? I mean, `comparable` is a contract, but it's being used as a constraint. Could you also write: contract Equaler(T) { T Equal(T) bool } > contract Comparable(T) { T comparable, Equaler } ? Or is comparable just special? Or does this not actually work, even for comparable? This would certainly be convenient if you could do it, though it means contracts involving a single type are privileged over others (you can create a disjunction between constraints, but not between contracts, for example). It seems like if you can create contract constraints like this, you'd also want to be able to make *generic* contract constraints, to capture things like contract Appender(type Elem)(T) { T Append(...Elem) T } contract Appendable(type Elem)(T) { T []Elem, (Appender(Elem)) // Parens to avoid parsing like a method constraint } The same issue comes up with the switch T.(type) { ... } idea. Even if you're only constraining one type at a time like this, you might still need to express a relationship to another type parameter. Unless this is allowed: switch (type) { case comparable(T): ... case Equaler(T): ... } On Fri, Aug 2, 2019 at 6:55 PM 'Axel Wagner' via golang-nuts < golang-nuts@googlegroups.com> wrote: > FWIW: > interface{}(a) == interface{}(b) > would work. It would panic if a and b have the same, non-comparable type. > But if you know the type is equal and comparable, it's well-defined and > does what you want. So you have to modify your code a bit: > > type equaler(type T) interface { > Equal(T) bool > } > > contract Comparable(T) { > T comparable, Equal(T) bool > } > > func Compare(type T Comparable)(a, b T) bool { > if eq, ok := a.(equaler(T)); ok { > return eq.Equal(b) > } > // Okay, this is weird, but: If you have `func (*T) Equal(T) bool`, a T > (value) would > // be accepted by the contract, as contracts don't distinguish between > value and > // pointer-receivers. But it would fail above type-assertion, as values > don't include > // pointer-methods in their method set. > if eq, ok := (&a).(equaler(T)); ok { > return eq.Equal(b) > } > return interface{}(a) == interface{}(b) > } > > I can't think of anything in the current design draft preventing this from > working (though I'm sure Ian can correct me if I'm wrong). > > It's a special case for equality-comparison though, it doesn't generalize > to any other operators. > > On Fri, Aug 2, 2019 at 10:40 PM Bruno Albuquerque <b...@gmail.com> wrote: > >> Ok, it makes sense. I do think that supporting something like this might >> make the proposal even more appealing as it will bring custom types >> somewhat closer to builtin types by allowing generic functions/methods that >> can act on both at the same time. >> >> On Fri, Aug 2, 2019 at 1:28 PM Ian Lance Taylor <i...@golang.org> wrote: >> >>> On Fri, Aug 2, 2019 at 1:12 PM Bruno Albuquerque <b...@gmail.com> wrote: >>> > >>> > I was thinking about a way to "extend" usual operations (say, >>> equality checks) to types that can not be compared the usual way (they are >>> not "comparable" in the contract sense) and came up with something like >>> this: >>> > >>> > // Just to use for type assertion later. >>> > type Equaler interface { >>> > Equal(Equaler) bool >>> > } >>> > >>> > contract Comparable(T) { >>> > T comparable(T), Equal(T) bool >>> > } >>> > >>> > func Compare(type T Comparable)(a, b T) bool { >>> > if eq, ok := a.(Equaler); ok { >>> > return eq.Equal(b) >>> > } >>> > >>> > return a == b // Does this work at all? >>> > } >>> > >>> > Would this work? More specifically it looks to me that that if the >>> specific type is not comparable (But has the Equal method), the compiler >>> might see the "==" comparison in the function and give an error. >>> > >>> > One way around this would possibly be to use something similar to type >>> assertion (in this case, a and b would have to be asserted to "comparable" >>> which I guess is not possible as it is a contract). Or, the compiler could >>> be smart enough to know that if we reached that check, then the type must >>> be comparable (so it would also not give an error). >>> >>> In the current design draft, that would not work. The == operator is >>> not supported by all possible types, so it is not permitted. >>> >>> We definitely don't want to rely on the compiler being smart enough. >>> Any such approach would require writing down the exact inference rules >>> that the compiler is permitted to use. Otherwise different compilers >>> would behave differently. >>> >>> One possibility we've toyed with is >>> >>> switch T.(type) { // Note: switch on type parameter itself, not a >>> value of that type. >>> case Equaler: >>> ... >>> case comparable: >>> // Permit using == operator here on values of type T in this >>> case only. >>> } >>> >>> We'll see whether some such facility seems useful. This is something >>> we can add later, if the current design draft seems workable. >>> >>> Ian >>> >> -- >> 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. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/golang-nuts/CAEd86Tz4tvx3qPZ4fV86AyV-B8YOXEMZMR-L4f6fcTyAuX_eXQ%40mail.gmail.com >> <https://groups.google.com/d/msgid/golang-nuts/CAEd86Tz4tvx3qPZ4fV86AyV-B8YOXEMZMR-L4f6fcTyAuX_eXQ%40mail.gmail.com?utm_medium=email&utm_source=footer> >> . >> > -- > 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. > To view this discussion on the web visit > https://groups.google.com/d/msgid/golang-nuts/CAEkBMfELVwJEkyLUJUsKGjUzqBVofDNRtkjta7%2BVXEFN_ZGtUg%40mail.gmail.com > <https://groups.google.com/d/msgid/golang-nuts/CAEkBMfELVwJEkyLUJUsKGjUzqBVofDNRtkjta7%2BVXEFN_ZGtUg%40mail.gmail.com?utm_medium=email&utm_source=footer> > . > -- 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. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CANjmGJvKgk5bFr7NM2m0EihQfb1XEXtYCdayNf-VHNUONV1UJw%40mail.gmail.com.