Why are these called "contracts"? It's just another generic type mechanism. "Contracts" are generally associated with entry and exit conditions for functions, and are not confined to single variables. A real contract looks like:
func foo(a integer, b integer)
{ entry(a>b);
...
}
Why not? They certainly define contracts for the type - at least that's my non-native speaker understanding of the english word.
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.
They want to avoid the term "generics" or "traits", same as how they avoided the word "exception" when they implemented "panic". golang likes to reinvent the wheel and call it something else just for the sake of it.
"When I use a word," Humpty Dumpty said, in rather a scornful tone, "it means just what I choose it to mean—neither more nor less." "The question is," said Alice, "whether you can make words mean so many different things." "The question is," said Humpty Dumpty, "which is to be master—that's all."
as I understand it (and I may be misunderstanding it), contracts are exactly like interfaces, except the type of parameters/return values is left to the implementation.
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 break
A 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 bases
> On a separate note, why is "contract" becoming a keyword instead of "type foo contract {}"?
I 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.
They address backwards compatibility in the document. It will only be a keyword in certain contexts so that any valid go1 code will still be valid go2 code.
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.
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:
and it would only be able to support adding an int to something, and returning an int. Doing this: will breakA contract for "adder" would look like:
You can then use this in a function by: which can then use any type that has an Add method 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: 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.,
feels much more consistent than no? (Perhaps it complicates parsing, though?)