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"? -Ben 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/CAL9jXCEmCLnxJE-uOF10ihC6eTXYZNV%2B%3DqBYLyTHYoT4z3Zycw%40mail.gmail.com.