On Thu, Sep 6, 2018 at 2:35 PM, jimmy frasche <soapboxcic...@gmail.com> wrote:
>
>> It's not necessary to support fields but I think it really is
>> necessary to support operators.  I claim that, other than type safe
>> data structures, the number one generic function that people want to
>> write is Min (or Max).  I don't think we can plausible add a generics
>> system to Go that doesn't permit writing a Min function.
>
> Hypothetically, if Go introduced generics where you couldn't write
> min/max but included min/max builtins, what's the next smallest
> example where operators are necessary?

// Contains returns whether v is in the slice s.
func Contains(type T)(s []T, v T) bool {
    for _, x := range s {
        if x == v {
            return true
        }
    }
    return false
}


> I'd be happy with generics if I needed to sometimes write a little bit
> of code to do a few  things but didn't have to write a tremendous
> amount of code to do most things. That seems like a good trade off,
> even if it's not necessarily a popular one.

But you can already do that, though, using interfaces.  Before we
added sort.Slice, people complained quite a bit about sort.Interface,
and that only required three lines.  Heck, people still complain that
we have sort.Ints but not sort.Int32s.


> But you can't really write a generic min/max with the contracts proposal.
>
> You can write a min/max that operates on all the ordered types, sure.
>
> (The one in the proposal has a bug because it accepts float types but
> doesn't handle the special cases for floats. That can't be repaired
> because while you could assert to float32 or float64 you couldn't
> assert to type MyFloat float64. Though I'm sure there's some contract
> where you can specify < but not floats.)

I think that for most people the Min I wrote above is acceptable even
for floats.

You can write one specifically for floats by having the contract
require convertibility to `float64`, and using `math.IsNaN`.


> You could also write a min/max that operates on types with a Less
> method, like you could under the various just-interfaces schemes.
>
> But you can't write one that works on both.

Yes.  Though I'm not clear on whether people want that.  I think we
need experience with real code here.

If experience show us that this is important, my current guess is that
the path forward here for Go is type adaptors, in which we say
something like "if T implements contract C1, then you can
automatically add this wrapper type and the wrapper type will
implement contract C2."  But I think that is clearly a problem for
later.


> Even ignoring that, the contracts proposal doesn't let you write a
> generic variadic min/max since there's no way to get the
> smallest/largest value of a type so you can't write
>
> func min(type T ordered)(ts ...T) T {
>   min := LargestPossible(T) // not possible
>   for _, t := range {
>     if t < min {
>       min = t
>     }
>   }
>   return min
> }
>
> You could get around that with the signature (firstOne T, rest ...T)
> but there's a larger point about the necessity of knowing numeric
> limits and properties for writing that kind of generic code in there.

I agree that this proposal doesn't help with numeric limits.  For that
you have to reach for the reflect package.  I don't know of any other
proposal that does any better in this regard.

For what it's worth, you can write variadic Min like this:

func Min(type T ordered)(s ...T) T {
    if len(s) == 0 {
        var zero T
        return T // or panic or something.
    }
    m := s[0]
    for _, v := range s[1:] {
        if v < m {
            m = v
        }
    }
    return m
}


> One way around the asymmetry between operators and methods that
> doesn't introduce any issues like operator methods or any of that is
> to have a package that defines types like
>
> package basic // not the best name
>
> type Int int
>
> type Slice(type T) []T
>
> // and so on for all the primitive and basic composite types
>
> and give all of those methods like Less and At. You'd have to do
> int(min(basic.Int(x), basic.Int(y))) but at least you wouldn't have to
> write the trivial wrapper methods. Not especially pretty.

I agree: not pretty.

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.
For more options, visit https://groups.google.com/d/optout.

Reply via email to