Skip to content

proposal: Go 2: replace contract kind lists with methods on built-in types #33410

Closed
@DeedleFake

Description

@DeedleFake

Just to clarify before I get started here: This is not a proposal for operator overloading. I completely agree with the arguments against operator overloading and do not want to see it in the language. Rather, this is essentially a proposal for the exact opposite.

The generics draft design, as it stands currently, allows two different features of types to be listed inside of contract specifications. You can list methods that the type must have, possibly with multiple options, and you can also list requirements on the underlying type. The primary purpose for the latter of these features is to allow certain operators to be used with types bound by the contracts inside of a function using it. For example,

contract Integer(T) {
  T int8, int16, int32, int64
}

func Min(type T Integer)(v1, v2 T) T {
  // Comparison is legal because it's legal for all the types in the contract.
  if v1 < v2 {
    return v1
  }
  return v2
}

However, I think that this actually completely unnecessary. I think that contracts can be simplified further by both removing the ability to specify underlying types and pre-defining methods that wrap each of the possible operators on a built-in type. For example, if there was a predefined method equivalent to func (v int) Less(v2 int) bool { return v < v2 }, then you could just do

contract Less(T) {
  T Less(T) bool
}

func Min(type T Less)(v1, v2 T) T {
  if v1.Less(v2) {
    return v1
  }
  return v2
}

and now any type that has support for a < operator is automatically covered as well as any user-defined types that have a method that fits the same pattern. This keeps contracts focused on the functionality, rather than the data layout. It also means that you can't create impossible contracts, as you can in the current design, as any set of methods with unique names is possible to define.

The hardest operation to define is probably type conversions. I'm not entirely sure how that should be handled, but one way would be to allow something like either typename(T) or T(typename) in the contract body to specify that a type can be converted to and from another one.

Edit: range could be a bit odd to use, too, especially because ranges over channels don't support the two-variable syntax for them.

All of the operator-wrapping methods could also be listed in the documentation of the builtin pseudo package for quick reference with go doc, possibly as methods on a fake type called Operator, or something.

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeLanguageChangeSuggested changes to the Go languageProposalgenericsIssue is related to genericsv2An incompatible library change

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions