A lot of those just pick out a subset of built-in types (or a type whose underlying type is a built-in). boolean is an obvious example, but arith is just all the numeric types.
We already have names for those: int, bool, etc. We just need to combine them with "or". E.g. bool is "underlying(bool)", complex is "underlying(complex64) | underlying(complex128)". I don't think any of the index or channel constraints are necessary. You can just put those in the function definition, e.g. func collect(type T)(c chan T) []T On Monday, September 10, 2018 at 7:45:04 PM UTC-4, Axel Wagner wrote: > > The unambiguous cases aren't ambiguous of course. It's the ambiguous cases > I'm concerned about :) My post and this thread contain a bunch of those. > They are mostly growing out of builtin functions and things like `range` > statements and index-expressions. > > You can translate all of my "pseudo-interfaces" into a clear and short > contract > > contract comparable (v T) { v == v } // also allows != > contract ordered (v T) { v < v } // also allows <=, >, >= > contract boolean (v T) { v || v } // also allows &&, ! > contract bitwise (v T) { v & v } // also allows |, ^, <<, >> > contract arith (v T) { v * v } // also allows +, -, / > // well, this one's a bit harder… > contract concat (v T) { v + v; v == "" } // also allows range, index[int], > copy > contract complex (v T) { real(v) } // also allows imag(v) > contract nilable (v T) { v == nil } // also allows != nil > > There is some discussion about maps, slices and channels to be had - but I > think the vast majority of interesting cases can be covered by taking e.g. > a `chan T`. A defined type with underlying type `chan T` is assignable to > that, so it would appear a perfectly fine way to express this contract > contract Chan (ch C, el T) { var x T = <-ch; ch <- x } > (and correspondingly for send/recv-only channels). > > You can't express field-accessors, which is an actual, inarguable > reduction in power that I'm perfectly fine with (similarly to how we're > fine with interfaces not being able to express that). > > Which IMO brings up the question: If we can express the vast majority (or > even all) of the needed contracts as combinations of this handful of > base-cases, why would we need to allow the full power of Go syntax, which > enables to write all the less than obvious ones too? > > (to re-emphasize: All of this isn't polished. I did sanity-check against > the examples in the contract design doc, but I have not put enough thought > into it that there might not be a couple nooks and crannies I haven't > thought of, as you've proven before :) ) > > On Tue, Sep 11, 2018 at 1:21 AM Jonathan Amsterdam <jbams...@gmail.com > <javascript:>> wrote: > >> >> >> On Monday, September 10, 2018 at 4:17:57 PM UTC-4, Axel Wagner wrote: >>> >>> On Mon, Sep 10, 2018 at 8:57 PM Jonathan Amsterdam <jbams...@gmail.com> >>> wrote: >>> >>>> FWIW, I think Ian's criticism of not wanting a list of new identifiers >>>>> to express operator constraints is fair. It is a genuine roadblock to c) >>>>> and if we're dead set of setting that as a baseline requirement, I agree >>>>> that a declarative/interface-based approach won't work. >>>>> >>>> >>>> I don't understand. Why are names so important? Why couldn't you use "T >>>> == T" to mean "T is comparable"? Or "To(From)" to mean "From is >>>> convertible >>>> to To"? >>>> >>> >>> It's not the name that is important, it's the declarative nature. I and >>> other people have already gone into detail with the problems we are having >>> with using imperative constructs to define constraints (mainly that they >>> are ambiguous and that it's hard both to enumerate the sets allowed by a >>> contract and to define a suitable contract for an intended set of >>> constraints). >>> >> >> I completely agree with you there (although I find the >> declarative/imperative terminology confusing). I think that except for >> interface-like constraints, we should be constraining by broad properties >> of types like comparable, ordered and numeric, rather than specific >> operations. >> >>> >>> >> I don't care if the declarative instruction is called "flooglehorn" or >>> "comparable". But I do care that it's an an actual declaration, mapping 1:1 >>> in a clear way to intent. Not an ambiguous statement from Go's current >>> Grammar. >>> >> >> It wouldn't be ambiguous. The spec would say "in type constraints, `T == >> T` means that T is comparable". I think people would learn to understand >> that, just as they understand that for a type T, `*T` means "pointer to T," >> not "dereference T". >> >> >> >> >>> >>> >> >>> Personally, I don't think that should be a requirement. Personally I >>>>> think it's worth adding extra identifiers, if we get declarative >>>>> constraint-specs for that - but that's just my opinion and everyone has >>>>> one >>>>> of those. >>>>> >>>>> But the issues you are bringing up are IMO not "fundamental'. a) to c) >>>>> from above aren't really touched by your criticism, AIUI. To me, they >>>>> seem >>>>> like issues of syntax and how to phrase the spec. >>>>> >>>>> But if generics are to have operator constraints like T == T, then >>>>>> something in the language has to change. Either not all interfaces are >>>>>> types, or some interfaces have methods that can't be called, or Go >>>>>> operators can have operands of different types. These changes are not >>>>>> minor >>>>>> tweaks: they alter fundamental aspects of the language. >>>>>> >>>>>> Contracts, on the other hand, are purely additive. They only come >>>>>> into play when writing generic code. If I'm not mistaken, the draft >>>>>> design >>>>>> doesn't change or even add anything to non-generic Go. There is >>>>>> something >>>>>> attractive about that orthogonality. >>>>>> >>>>> >>>>> I agree. I think that's fair. I don't think for that they need to be >>>>> imperative specifications though. >>>>> >>>>> (or, allow embedding interfaces into contract-declarations, remove >>>>>>> the "type-checking function body" idea and instead define a set of >>>>>>> base-contracts you can use for operators) and you'd end up with pretty >>>>>>> much >>>>>>> my design. >>>>>>> >>>>>> >>>>>> That doesn't sound like your original design at all. >>>>>> >>>>> >>>>> You need to squint harder :) From the rest of your mail, ISTM that we >>>>> are putting emphasis on different aspects of my description and the >>>>> contracts design. What I was trying to say is that IMO the things about >>>>> my >>>>> design I like and the things about the contract design you like can >>>>> probably be reconciled. >>>>> >>>>> The first seems problematic, because for multi-parameter contracts you >>>>>> wouldn't know which type the parameter referred to. >>>>>> >>>>> >>>>> FWIW (we are now getting lost in ifs-and-buts and it's no longer clear >>>>> what the specific ideas are we are talking about), in my original design >>>>> as >>>>> well as that ad-how handwaving you're quoting, constraints always apply >>>>> to >>>>> a single type and you'd use parametric interfaces (or… interfaces+) to >>>>> express simultaneous restrictions. >>>>> >>>>> But FTR, I did not intend to start an actual discussion around that, >>>>> its far too underspecified for that. I was sincere when I said your >>>>> criticism is fair and that I had to think about it. My handwaving was >>>>> just >>>>> to explain why I don't think it can justifiable be called a >>>>> *fundamental* issue. >>>>> >>>>> >>>>>> The second seems reasonable to me. Now we can talk about issues like >>>>>> whether this adds too many names to the language, or whether you've >>>>>> described all the important constraints (I think conversion and >>>>>> assignability are important, for instance). >>>>>> >>>>> >>>>> Again, the caveat of handwaving still applies (IMO we should constrain >>>>> ourselves to talk about sufficiently spelled out designs - Ian's contract >>>>> design qualifies and I'd also feel fine with the thing I wrote down in my >>>>> blog, as long as we agree that its conditional on polishing the "are >>>>> pseudo-interfaces usable as types" question), but: Given that we have >>>>> type-parameters, adding that is fairly straightforward in the form of (in >>>>> the words of my blog post) parametric pseudo-interfaces >>>>> "convertible{To,From}(T)" and "assignable{To,From}(T)". >>>>> >>>>> But yeah, talking about in too much depth here would IMO constitute >>>>> high-jacking of threads about Ian's design. I'm also totally cool to >>>>> start >>>>> a new thread about this after I had time to incorporate your feedback. >>>>> Unfortunately this isn't my job, so I have to find time between other >>>>> things :) >>>>> >>>>> Anyway. I think I've been ranty enough for today :) >>>>> >>>>> On Sunday, September 9, 2018 at 5:21:28 PM UTC-4, Axel Wagner wrote: >>>>>>> >>>>>>> I don't think saying that is is productive. contracts are more than >>>>>>> just "identifiers used as constraints", they are also a syntactic >>>>>>> construct >>>>>>> to specify those. I specifically don't allow that and that's the whole >>>>>>> point I'm making. So this doesn't seem like a particularly nice way to >>>>>>> have >>>>>>> a discussion. >>>>>>> >>>>>>> But yes, if it makes you happier, we can call them "contracts", >>>>>>> allow to embed them into interfaces and remove contract declarations >>>>>>> from >>>>>>> the design (or, allow embedding interfaces into contract-declarations, >>>>>>> remove the "type-checking function body" idea and instead define a set >>>>>>> of >>>>>>> base-contracts you can use for operators) and you'd end up with pretty >>>>>>> much >>>>>>> my design. >>>>>>> >>>>>>> On Sun, Sep 9, 2018 at 11:17 PM Jonathan Amsterdam < >>>>>>> jbams...@gmail.com> wrote: >>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> On Sunday, September 9, 2018 at 3:19:16 PM UTC-4, Axel Wagner wrote: >>>>>>>>> >>>>>>>>> On Sun, Sep 9, 2018 at 8:49 PM Jonathan Amsterdam < >>>>>>>>> jbams...@gmail.com> wrote: >>>>>>>>> >>>>>>>>>> The problem is that this program seems to type-check, but it is >>>>>>>>>> invalid. The == operator is specified to work on operands of the >>>>>>>>>> same type, >>>>>>>>>> and it is being used on operands of different types. >>>>>>>>>> >>>>>>>>> >>>>>>>>> Good point. I have to think about it. An ad-hoc solution, FWIW, >>>>>>>>> would be to only take into account (or allow) pseudo-interfaces for >>>>>>>>> type-constraints. >>>>>>>>> >>>>>>>> >>>>>>>> The draft design has a name for those: contracts. >>>>>>>> >>>>>>>> -- >>>>>>>> You received this message because you are subscribed to the Google >>>>>>>> Groups "golang-nuts" group. >>>>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>>>> send an email to golang-nuts...@googlegroups.com. >>>>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>>>> >>>>>>> -- >>>>>> You received this message because you are subscribed to the Google >>>>>> Groups "golang-nuts" group. >>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>> send an email to golang-nuts...@googlegroups.com. >>>>>> For more options, visit https://groups.google.com/d/optout. >>>>>> >>>>> -- >>>> You received this message because you are subscribed to the Google >>>> Groups "golang-nuts" group. >>>> To unsubscribe from this group and stop receiving emails from it, send >>>> an email to golang-nuts...@googlegroups.com. >>>> For more options, visit https://groups.google.com/d/optout. >>>> >>> -- >> You received this message because you are subscribed to the Google Groups >> "golang-nuts" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to golang-nuts...@googlegroups.com <javascript:>. >> For more options, visit https://groups.google.com/d/optout. >> > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.