On Tue, Sep 11, 2018 at 4:39 PM Larry Clapp <la...@theclapp.org> wrote:
> Directly accessing a field in a generic struct might be *rare*, but it > seems like it shouldn't be *impossible*. > I think it would be better if it is, but if it introduces additional cost, that cost needs to be weighed against the benefit :) That's why having real use cases is useful :) > If you're going to argue that "you can just write access functions" > Note that there is a difference in what I provided, in that it actually doesn't require the *user* of the type to write any boilerplate (and the author only has to write a tiny amount). This is already progress over the current situation :) > , 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> 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. >>> 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. > -- 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.