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.

Reply via email to