1. 27

  2. 32

    I am still extremely annoyed that this is being called “Contracts,” and has nothing to do with Design by Contract in the traditional sense, e.g., “correctness.”

    This type of definition hijacking makes jargon even worse than it already is, and we lose our ability to clearly, and succinctly communicate when terms are reused for completely different things.

    1. 18

      I also found that annoying and confusing. It’s almost like they are conceding the fight to add generics to the language without admitting defeat. I cannot think of any other reason why they would do this..

      1. 0

        After implementing polymorphic collections in the standard library by silently downcasting to interface{}, I don’t think they have anything to lose.

        1. 2

          I believe the plan here is to reimplement that using generics.

    2. 8

      I’m still unconvinced contracts need to be strictly separate from interfaces. The argument that enforcing operators would be repetitive maybe falls flat on me because it seems trivial to ship the stdlib with some basic Operatable interfaces you can reach for, but also that doing a bit of extra typing for clarity I’ve generally seen as part of the golang ethos.

      Similarly, the idea that you can never have discrete instances of contracts (versus interfaces) runs counter to how I’ve used generics in the past where generic constraints are just interfaces and you can reference the type constraint interface when declaring values later.

      1. 6

        Agreed on interface reuse. My guess is adding new semantics to interface is hard to back out of, where as “contracts” can just ultimately be deprecated when the dictators decide that the experiment “failed.”

        OK, maybe that’s not fair. But, I agree that there’s a weird resistance to extend something that seems to really make sense, in favor of adding something completely new. Either way, 3rd party tooling will be broken until updated…

        1. 2

          They extended functions and types to accept type parameters, but then they neglected to do the obvious thing which is extend interfaces with type parameters. Do that, then allow interfaces to be the specifiers in the type parameters list - done. They dedicated a whole section to this but every argument is unconvincing and evinces a lack of imagination. Just read this:

          Contracts, unlike interfaces, support multiple types, including describing ways that the types refer to each other.

          Then add type parameters to the interfaces.

          It is unclear how to represent operators using interface methods.

          Other languages either map operators to a special name or provide a syntax for the overloading. Most design documents have a prior art section - do your homework!

          An interface is a type, not a relationship between function definitions and callers. A program can have a value of an interface type, but it makes no sense to speak of a value of a contract type.

          Again, there is no creativity here or an attempt to see what other people have done. Expand the definition of interface. I would solve the problem like this: if an interface appears in a type parameter list, the type is unboxed and preserves its type, whereas if it occurs in a parameter list as a type, then it is the usual boxed interface. It is really that simple. This also happens to be nearly exactly what Rust did for a long time.

          In other words, contracts are not extensions of interface types.

          This is wrong. It’s wrong, it’s wrong, it’s wrong.

          I will end this comment with just a little bit of polemic, which by now is par for most comments about Go but totally deserved: I do not trust the language designers. There is too much NIH syndrome, too much anti-intellectualism, too much reinvention of solved problems. It is a waste of a great runtime. Use something else.

          1. 7

            do your homework!

            It seems manifestly obvious that they did, considering the design document cites numerous languages and how their design improves on past mistakes. Consider cutting back on your hyperbolic ranting and snobbery; it undermines your commentary.

            1. 2

              That comment was specifically about the preceding quotation.

              1. [Comment from banned user removed]

                1. 3

                  He is on the Rust team…

                  1. 0

                    That’s an appeal to authority and you know that.

                    Also, being an authority doesn’t stop you from being an ass because you misinterpreted someone else’s comment as being “I am very smart” to utterly dismiss their content.

                    1. 6

                      no, i mean @soc said that @kristof was criticizing @burntsushi’s language.

                      but thats not the case. the language being criticized is Go, and AFAIK @burntsushi has nothing to do with Go, other than maybe being a user. He is on the Rust team, hence my comment. Sorry that was not clear. i mean just look at this bio:


              2. 2

                They extended functions and types to accept type parameters, but then they neglected to . . . extend interfaces with type parameters.

                Although the draft doesn’t explicitly mention interfaces as a possible parameterized type, I don’t see anything that would imply they aren’t supported.

            2. 3

              TL;DR: The generic syntax from D, with Rust’s traits renamed as contracts.

              1. 1

                Would it be possible to do something like return an arbitrarily sized array using this? Say a function wants to return *[8]uint64. You need to write a new function for every (size, type) combination. I don’t think this proposal helps here.

                1. 4

                  From “Omissions”:

                  No parameterization on non-type values such as constants This arises most obviously for arrays, where it might sometimes be convenient to write type Matrix(type n int) [n][n]float64. It might also sometimes be useful to specify significant values for a container type, such as a default value for elements.

                2. 0

                  Seems ok, sad they don’t talk about retrofitting maps and channels to use generics or discuss why it isn’t possible and what the tradeoff s are.

                  1. -1

                    Can’t say I’m in love with the syntax, this seems needlessly heavy-handed

                    func (r *receiver) Name(type T)(a, b int, T) ([]T, error) { ... }

                    I would have preferred the Java-style

                    func (r *receiver) Name(a, b int, <T>) ([]<T>, error) { ... }

                    But either way I’m excited for the prospect of writing generic code in Go!

                    1. 4

                      They explain why they chose not to use angle brackets.

                      1. 3

                        looks like only difference was <T> replaced with (type T) - yeah it more verbose but its one less layer of nesting and i would argue more readable - also it seems you are misrepresenting the syntax - look at this

                        type Set(type Elem comparable) map[Elem]struct{}
                        func (s Set(Elem)) Len() int {
                           return len(s)