Operator overloading will never -- hopefully -- be implemented. It's a
perfect way to obscurate code. --Kent


On Fri, Aug 7, 2020 at 4:33 PM Patrick Smith <pat42sm...@gmail.com> wrote:

> I like the second draft for generics. It seems to me a large
> simplification and improvement over the first draft. Considering just
> the state of Go today, I would be quite happy with this, even if it's
> not perfect. Thanks to Ian, Robert, and everyone else for their work
> on this.
>
> Also, I would vote for square brackets over parentheses.
>
> But I do have concerns related to the future development of Go. In
> particular, if we think it likely that a future version of Go will
> allow operator overloading, then perhaps type lists are not the best
> choice.
>
> To my mind, the biggest defect in the design draft is that we can't
> write generic functions and types that work transparently with both
> builtin and user-defined types (that do not inherit appropriate
> behavior from an underlying builtin type). For example, we can't write
> a
>
> func Min[type T ...](a, b T) T { ... }
>
> that works both when T is int and when T is
>
> type BigInt struct { i *big.Int }
>
> Instead, we would use workarounds such as writing two versions of Min,
> or passing in an adaptor function or object; in the case of Min, a
> comparison function. And that's OK, especially in an initial version
> of generics.
>
> But generics would be significantly easier to use if we could write
> functions that work on both builtin and user-defined types. The two
> most likely candidates for allowing this seem to be operator
> overloading (where BigInt might have a method named "<", "operator<",
> or some such, that allows it to be used with the < operator) and
> methods on builtin types (where int might be given a method named Less
> with the same behavior as the < operator). Of course, other solutions
> could be imagined, but I'll confine my speculations to those two.
>
> Now let's try to imagine how sorting slices might be implemented in
> the standard library in various futures.  Of course, the current sort
> package would have to be kept and maintained for a long time.
>
> If Go2 implements the current draft with type lists, then we might add
> a sort2 package containing something to:
>
> func SliceBy[type T](s []T, less(T, T) bool) { ... }
>
> type Ordered interface {   // Copied from the draft
>     type int, int8, int16, int32, int64,
>     uint, uint8, uint16, uint32, uint64, uintptr,
>     float32, float64,
>     string
> }
>
> func Slice(type T Ordered)(s []T) {
>     SliceBy(s, func(a, b T) bool { return a < b })
> }
>
> type Lesser[type T] interface { Less(T) bool }
>
> func SliceByLess(type T Lesser[T])(s []T) {
>     SliceBy(s, T.Less)
> }
>
> All well and good. Now say time goes by and Go3 adds operator methods.
> Nothing in the sort2 package expresses a unified sort using operator
> methods, so we need a new package sort3:
>
> func SliceBy[type T](s []T, less(T, T) bool) { ... }
>
> type Lesser[type T] interface { <(T) bool }   // Or whatever the syntax is.
>
> func Slice(type T Lesser)(s []T) {
>     SliceBy(s, func(a, b T) bool { return a < b })
> }
>
> (We might just add sort3.Lesser and sort3.Slice into the sort2 package
> under different names, but I suspect the aim would be to eventually
> deprecate sort2.)
>
> The effects will ripple through other code, both in and outside the
> standard library. Suppose some Go2 code has a chain of generic
> functions A calls B calls C calls D, where each exists in two
> versions, one for builtin types and one for user-defined types, and
> the two versions of D call sort2.Slice or sort2.SliceByLess. When Go3
> with operator methods arrives, if we want to unify these, we have to
> write a third version of each of A, B, C, and D, where D calls
> sort3.Slice.
>
> On the other hand, suppose Go2 has type lists and Go3 gives builtin
> types methods corresponding to operators. Assuming the name Less is
> used for <, sort2.SliceByLess now handles both builtin and
> user-defined types, so we don't need a sort3 package. And in the ABCD
> scenario, we can just keep the SliceByLess version of each, and
> quietly let the sort2.Slice versions vanish as they become unused.
>
> [Important point===>] This means that if Go2 has type lists in
> interfaces, there will be a strong incentive for Go3 to give builtin
> types methods, even if we think that operator overloading is otherwise
> a superior solution, because operator overloading will require much
> more new code to be written.
>
> Instead of using type lists, suppose Go2 allowed interfaces to require
> the presence of specific operators. Then the sort2 header might look
> like this:
>
> func SliceBy[type T](s []T, less(T, T) bool) { ... }
>
> type Lesser[type T] interface { <(T) bool }
>
> func Slice(type T Lesser)(s []T) {
>     SliceBy(s, func(a, b T) bool { return a < b })
> }
>
> type MLesser[type T] interface { Less(T) bool }
>
> func SliceM(type T MLesser[T])(s []T) {
>     SliceBy(s, T.Less)
> }
>
> (Note that the first part is identical to the previous sort3 header.
> But in Go2 we also need MLesser and SliceM in order to handle
> user-defined types.)
>
> This leaves us more easy options in Go3. If Go3 implements operator
> overloading, then sort2.Slice now handles both builtin and
> user-defined types, and code using sort2.SliceM can be allowed to
> wither away. If Go3 implements an int.Less method, then sort2.SliceM
> is now the good version, and code using sort2.Slice can be allowed to
> wither away as it becomes unused.
>
> So maybe the alternative of allowing interfaces to require specific
> operators deserves another look, to see if it's really not viable in
> Go2. I would suggest that perhaps the initial version of generics need
> not support all operators; maybe it's enough to support only those
> that apply to numeric types (string should be accepted by interfaces
> requiring +, <, and other comparison operators). Or maybe a slightly
> larger subset of operators would do.
>
> As a final note - this post, like all speculations about the future,
> is rather fuzzy. I realize that. Nevertheless, I think it is important
> to realize that the choices we make now carry consequences for our
> options after a few years' time.
>
> --
> 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/CAADvV_stjEvD4pLwGNmahAEzc0UDNLuzwttZ9wDg78BOJfDA5Q%40mail.gmail.com
> .
>

-- 
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/CAHC_roHqFGXhLrJKKvsgGa_y3F-Qh%2Bz%2BJf33uNrFXLbmwi_QUw%40mail.gmail.com.

Reply via email to