The Updated Draft Design for Go 2 Contracts
go.googlesource.com
go.googlesource.com
func foo(a integer, b integer)
{ entry(a>b);
...
}It might seem weird if one used a different programming language which used the term for a slightly different concept - but that doesn't mean Go's usage is bad.
The concept is similar to what concepts are in C++ and traits in Rust. And from those terms I actually find contract to be the most understandable for people who are new to these things.
It looks quite sensible, and much better as the current //go: generate solution.
contract Zero(T) {
Zero() T
}
> We feel that more experience with this design is needed before deciding what, if anything, to do here.Hopefully the more experience leads the Go designers to solutions some production-quality languages already have to solve this :)
So an interface of "adder" would look like:
type adder interface {
Add(int) int
}
and it would only be able to support adding an int to something, and returning an int.
Doing this: func AddStrings(a adder, b string) string {
return a.Add(b)
}
will breakA contract for "adder" would look like:
contract adder(T) {
T Add (T) T
}
You can then use this in a function by: func addTheThings(type T adder)(t1, t2 T) T {
return t1.Add(t2)
}
which can then use any type that has an Add method //can't extend native types, so we have to create an alias and extend that
type Addstring string
func (a Addstring)Add(b Addstring) Addstring {
return a+b
}
func (a Banana)Add(b Banana) Banana {
return Banana{a.Count + b.Count}
}
then your "addTheThings" function can operate on strings (via the Addstring type) and Bananas, and anything else that fulfills the contract. So the original example: func AddStrings(a adder, b string) string {
if as,ok := a.(Addstring); ok {
return a.Add(b)
}
//raise an error here
}
On a separate note, why is "contract" becoming a keyword instead of "type foo contract {}"?
Making the common business concept of "contract" a keyword is likely to break backward compatibility for some code basesI was wondering about this too. It also just feels really weird since it's a different construction than any of the other types.
Maybe the thinking is because a contract is not a type? But so what...
On first blush, it also feels weird that type is coming _before_ the type arguments, rather than after -- since types for normal arguments come after the argument.
E.g.,
Map(T, U type)(t []T, f func(T) U) []U
feels much more consistent than Map(type T, U)(t []T, f func(T) U) []U
no? (Perhaps it complicates parsing, though?)"type T adder" means "in this scope, declare T to be a type adhering to the adder contract"