Hi, Axel, You're certainly right: we can *get around* not having access to specific fields in generic functions. And my MinKeys example may've been suboptimal, or not a great example to begin with.
And the fact that you have to hard-code the field name(s) to be accessed in the contract also seems a little sub-optimal. On the other hand, trying to figure out a reasonable way to make the field names variable would probably be worse. ... Even just trying to come up with an example here got ugly pretty quickly. I guess I kind of imagine that, for any example in the draft, you could put the generic variable in a struct, and there you'd have accessing a field in a generic struct type. Directly accessing a field in a generic struct might be *rare*, but it seems like it shouldn't be *impossible*. If you're going to argue that "you can just write access functions", well, then it seems like the whole generics discussion could be rebutted with "but you can just write a code generator", and with the same rejoinder (to wit, more or less, "that's what the compiler *is*, and we're trying to standardize it and make it easier"). — L On Tuesday, September 11, 2018 at 9:53:33 AM UTC-4, Axel Wagner wrote: > > Hi Larry, > > On Tue, Sep 11, 2018 at 3:25 PM Larry Clapp <la...@theclapp.org > <javascript:>> wrote: > >> This question frankly struck me odd, given the context. To paraphrase: >> "Do I have examples of where accessing a field in a generic struct type >> might be useful?" I kind of assumed that, hip-deep as we are in a >> discussion of generic functions, that such a thing might be understood? I >> mean, accessing struct fields in functions is ... useful? Would not >> accessing struct fields in generic functions be ... similarly useful? >> > > TBH I'm not sure. Struct fields, to me, have always been a property of a > concrete type and I don't see a need to abstract over them. Maybe I'm > suffering from Stockholm syndrome, but consider that Go *never* had the > ability to specify existence of fields in an interface - and that's not > because it would've been very hard to implement. > > 1. The draft proposal discusses the Corresponding function, to assign >> fields of the same name from one struct to another, of different types ( >> here >> <https://go.googlesource.com/proposal/+/master/design/go2draft-contracts.md#fields> >> ). >> > > I saw that example and I find it kind of contrived (as I said in the new > thread I started). If you look at the examples section in the design doc, > they are all very practical and motivated by experience reports. Or to put > it another way: This example looks an awful lot like "because we can", not > a "we need to, because". > > 2. To quote the draft proposal, "ever popular Min and Max functions", as >> applied to structs. >> > > Personally, I find that an odd case to make. The function would inherently > prescribe the field name to sort by (so, e.g., you couldn't sort a > "Person"). So to use it, you already need some control over the struct. But > if you have that control, then why not > > type Key(type T ordered) T > func (k Key(T)) SortKey() T { return k } > > contract key(v T) { > var _ interface{SortKey() T} = v > v.SortKey() < v.SortKey() > } > > func MinKeys(type T key) (x, y T) T { > if x.SortKey() < y.SortKey() { > return x > } > return y > } > > used as > > type MyStruct struct { > sort.Key(string) > Other int > Field float64 > } > > I'd argue that is… the same-ish? It's a little bit more code, but it also > allows a) the MinKeys function to be used with any defined type, by adding > a method to it, b) to unexport the method name of the interface, so you > actually get package-scoped requirements on "keys" (i.e. a crypto.Key > contract and a sort.Key contract wouldn't collide) and c) used just as > conveniently, once you accept that putting a constraint on the name of a > field is similar to putting a constraint on the field being an embedded > field of a specific type. > > i.e. IMO it's strictly more generic and useful. > > >> Somewhat to my surprise, the draft doesn't actually give a sample >> implementation of these, at least not that I could find. So here's my >> attempt: >> > >> contract key(x T) { >> x.Key < x.Key // specify that T must have a Key field and that >> it must be ordered >> } >> >> func MinKeys(type T key)(x, y T) T { >> if x.Key < y.Key { >> return x >> } >> return y >> } >> >> So, I think accessing fields of generic struct types would be handy, yeah. >> >> — L >> >> On Tuesday, September 11, 2018 at 6:54:06 AM UTC-4, Jonathan Amsterdam >> wrote: >>> >>> Do you have actual examples of how that would be useful to you? >>> >>> On Monday, September 10, 2018 at 9:45:12 PM UTC-4, Larry Clapp wrote: >>>> >>>> The conversation here is deep, and I haven't followed all of it. I >>>> *think* y'all are discussing some different contract system than the >>>> actual draft proposal? >>>> >>>> If that's the case: >>>> >>>> You can't express field-accessors, which is an actual, inarguable >>>>> reduction in power that I'm perfectly fine with >>>> >>>> >>>> How would you instantiate a generic function that wanted to access >>>> field F of a generic type T? >>>> >>>> if you can't do that, well, I'm not fine with that. >>>> >>>> But I may have misunderstood. >>>> >>>> — L >>>> >>>> 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 :) ) >>>>> >>>> [snip] >> >> -- >> 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.