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 <[email protected]> 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 <[email protected]> wrote:
>
>> On Fri, Aug 2, 2019 at 1:12 PM Bruno Albuquerque <[email protected]> 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 [email protected].
> 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 [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/golang-nuts/CAEkBMfELVwJEkyLUJUsKGjUzqBVofDNRtkjta7%2BVXEFN_ZGtUg%40mail.gmail.com.