On Thu, Jul 2, 2020 at 9:02 PM Ben Hoyt <benh...@gmail.com> wrote: > > Thanks. You're right about the Map with the comparison function being > more flexible. That helps allay my concerns for ordered data > structures. > > I guess what I'm worried about is for someone writing a "slices" > library and wants to include a function like slices.Smallest(). Do > they give it an Ordered type-list constraint or an constraint with a > Less method? How will they know which of the following to do? > > 1) Only include Smallest() and hope nobody who uses big.Int comes along. > 2) Include two versions, Smallest(type T Ordered)(s []T) for int and > float64 etc, and SmallestCmp(type T)(s []T, func (x, y T) int) so > people can use SmallestCmp(bigs, big.Int.Cmp)? > 3) Something else, like Smallest() plus a SmallestCustom() that uses > CustomOrdered > > Can you flesh out what you're thinking of w.r.t Smallest() and taking > "an approach like the sort example"?
I was thinking of a comparison function, with a wrapper that uses a little comparison function that calls Less. It's more work on the package writer side, but it seems pretty straightforward on the part of the caller of the function. I think we are always going to face this dichotomy unless we introduce a large set of standard methods for builtin types, or add some way for people to define operator methods for their own types. Both seem like big changes to the language, and while they would be convenient for certain uses of generics it's not clear to me that they are essential. That is, I think generics can be useful even without those features, and I don't think generics precludes adding those features later if they seem useful. Ian > On Fri, Jul 3, 2020 at 3:37 PM Ian Lance Taylor <i...@golang.org> wrote: > > > > On Thu, Jul 2, 2020 at 4:59 PM ben...@gmail.com <benh...@gmail.com> wrote: > > > > > > This thread on lobste.rs made me wonder if the difference between > > > type-list constraints and method-interface constraints is going to cause > > > a bunch of issues or code duplication. There's a lack of orthogonality > > > here that makes me uneasy. > > > > > > For example, the Smallest() function in this proposal takes a slice of > > > []T, where T is "type T constraints.Ordered", a type-list based > > > constraint. That means Smallest() will only work with the built-in types > > > specified in the type list (or types with one of those as an underlying > > > type), and can't be used with more complex struct types. > > > > > > For it to work for other types, you'd have to write a second version of > > > Smallest() -- code duplication -- that took a method-interface based > > > constraint like so: > > > > > > type CustomOrdered(type T) interface { > > > Less(other T) bool > > > } > > > > > > Arguably Smallest() would still be quite useful even if it only works for > > > builtin integer and float point types, but with the type-list Ordered it > > > wouldn't work for (say) big.Int, a custom Decimal type, or a more complex > > > struct type. > > > > > > But I think this is worse for ordering-based *data structures* like Tree > > > of T. If done with the type-list Ordered, the tree could only store > > > built-in types, which isn't that useful. Using a constraint like > > > CustomOrdered would work and be more flexible ... but then a basic > > > Tree(int) wouldn't work. You'd have to do Tree(MyInt) and convert > > > everything from int to MyInt on the way in, and MyInt back to int on the > > > way out -- a bunch of type conversion boilerplate. > > > > > > Or you'd end up writing two versions of your generic Tree: BuiltinTree > > > that uses Ordered (type lists), and CustomTree that uses CustomOrdered > > > (interface with Less). Not very nice. > > > > > > (Here's some Go2Go code which shows this for Smallest: > > > https://go2goplay.golang.org/p/Rbs374BqPWw) > > > > > > I'm not sure how the proposal solves this for something like Smallest() > > > ... I don't think it does. For ordered data structures, like the Map > > > example, it passes in a custom "compare" function to the initializer and > > > kind of side-steps the issue. Which isn't bad for data structures as it'd > > > still eliminate a lot of code, but it would be kind of a pain for little > > > algorithms like Smallest(). > > > > > > Thoughts? > > > > What you say is true. I don't know of a way around the basic problem > > other than introducing methods on basic types. That would be a big > > change to the language, and would require introducing a large number > > of new names. > > > > The way I would suggest handling your Tree example is by making the > > basic data structure take a comparison function. Then you can write > > tiny wrappers that create the function for any ordered type, or for > > any type with a Less method. Or people can just pass their own > > comparison function. You suggest that the Map example sidesteps the > > issue by using a comparison function, which is true, but the Map data > > structure is also more flexible with a comparison function. For > > example, it lets you store the same type in multiple types with > > different sorting. > > > > The Smallest example is a case where we don't need to store the value, > > so you can take an approach like the sort example in the design draft > > (https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md#sort). > > > > I'm not going to claim that these are perfect solutions, but they seem > > workable to me. It would be interesting to hear of real cases where > > they are problematic. > > > > Ian -- 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. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAOyqgcVOxntTxirb-A5o1MuFhMt7nMP9cqpNgcWknSFcV3Y3Vg%40mail.gmail.com.