Instantly share code, notes, and snippets.

# deanveloper/WhyContracts.md

Last active October 30, 2018 17:06
Show Gist options
• Save deanveloper/c495da6b9263b35f98b773e34bd41104 to your computer and use it in GitHub Desktop.

It is unclear how to represent operators using interface methods. We considered syntaxes like +(T, T) T, but that is confusing and repetitive. Also, a minor point, but ==(T, T) bool does not correspond to the == operator, which returns an untyped boolean value, not bool. We also considered writing simply + or ==. That seems to work but unfortunately the semicolon insertion rules require writing a semicolon after each operator at the end of a line. Using contracts that look like functions gives us a familiar syntax at the cost of some repetition. These are not fatal problems, but they are difficulties.

Do these problems really justify creating an entirely new construct that has a very similar purpose to something we already have?

Is there really no other solution? We could do `operator[<op>]` or something similar instead...

Some common interfaces people may be using

```// Describes bool, complex, pointers, channels, interfaces,
// some structs, some arrays, strings, floats, and ints.
type Comparable interface {
operator[==]
operator[!=]
}

// describes strings, floats, ints
type Orderable interface {
Comparable
operator[<]
operator[>]
operator[<=]
operator[>=]
}

// describes floats and ints
type RealNumeric interface {
Comparable
operator[+]
operator[-]
operator[*]
operator[/]
operator[%]
}

// describes ints
type BinaryNumeric interface {
RealNumeric
operator[<<]
operator[>>]
operator[&]
operator[|]
operator[^]
operator[&^]
}```

For a `Graph` interface:

```type Edge interface {
Nodes() (Node, Node)
}
type Node interface {
Edges() []EdgeInterface
}

type Graph(type N Node, E Edge) struct {
// ...
}

func (type N Node, E Edge) NewGraph(init []N) *Graph(N, E) {
// ....
}```

For a `Sum` method:

```type Addable interface {
operator[+]
}

func (type T Addable) Sum(t ...T) {
var sum T
for _, elem := range t {
sum += elem // since + is defined for T, we may do this
}
return sum
}

func main() {
Sum(5, 6, 9) // returns 20

Sum("woah", "strings") // returns "woahstrings"
}```

Doing this we could also redefine a lot of the things in `builtin.go`

```type bool comparable
type complex64 comparable
type complex128 comparable

type string orderable

type float32 realnumeric
type float64 realnumeric

type int binarynumeric
type int8 binarynumeric
type int16 binarynumeric
type int32 binarynumeric
type int64 binarynumeric
type uint binarynumeric
type uint8 binarynumeric
type uint16 binarynumeric
type uint32 binarynumeric
type uint64 binarynumeric
type uintptr binarynumeric

type rune = int32
type byte = uint8```

The only issue I can find now is that there is no way to generalize `complex64` and `complex128`. You are able to do this with contracts using `contract Complex(c C) { imag(c) }`, but there is no way to do this in Go. But honestly, it might be best to just remove `complex`, add operator functions, and create a `math/complex` package.

### jimmyfrasche commented Sep 12, 2018

What do operators in interfaces mean when used as regular interfaces rather than as constraints?

``````var a, b Orderable = 1, "hi"
_ = a < b
var c Orderable
_ = a < c
``````

### deanveloper commented Sep 14, 2018

Hmm, you are right about that, and I never considered it. That's a really simple case that I never really thought of. I might make a new proposal which addresses this, I have some ideas though.

I think contracts are okay, but they are very similar to interfaces. One of my favorite things about Go is that there are very few ways to do the same thing, so when we have both contracts and interfaces, it kinda throws me for a loop.

### johnw42 commented Sep 20, 2018

I think this proposal could be combined with this one, which uses pre-defined contracts for language primitives. Just make those contracts into special built-in interfaces. The compiler knows which operators are valid for a given interface, so there's no need to have any syntax for specifying them.