A problem with the draft generics design (and with most of the alternative 
proposals including my own) is that, without operator overloading, there 
appears to be no way to unify the sorting functions.

This is because only the numeric and string types support the ordering 
operators (<, <=, >=, >, ==, !=). Other types have to satisfy the 
sort.Interface and its Len, Less and Swap methods which the built-in types 
don't have.

Attempts to solve this problem usually try to link the ordering operators 
with named methods. However, this isn't very satisfactory because the 
built-in types don't have any methods and therefore need to be wrapped in 
types which do.

Suppose we turn this strategy on its head and instead allow types which 
wouldn't otherwise do so support the ordering operators provided they 
satisfy a simple interface. This interface would have a single method which 
returned a string representation of an object of that type and the compiler 
would use this string to implement the ordering operators.

A natural home for this interface would be the 'sort' package and here's a 
possible definition (yeah, the names may need some work):

type Orderer interface {
    OrderString() string
}

You couldn't just use the fmt.Stringer interface instead because you'd 
usually want a type to be displayed in a different way to how it was 
sorted. 

So, as an example of how this might work, suppose we have this simple 
struct:

type Person struct {
    Name string
    Id, Age uint
}

and we'd like it to be sorted first by name and then (if the names are 
equal) by *decreasing* order of age. We could then give it the following 
method:

func (p *Person) OrderString() string {
    return fmt.Sprintf("%s%03d", p.Name, 200 - p.Age)
}

which would enable us to do this:

p1 := Person{"Donald", 1, 20}   // stringifies as Donald180
p2 := Person{"Donald", 2, 72}   // stringifies as Donald128 
b := p1 < p2  // false because p2 is older and therefore sorts first

Now, technically this wouldn't be operator overloading - it would be built 
into the language. As such, it would be backwards compatible.

'Stringifying' an object isn't always perfect - and may be inefficient for 
large collections which are sorted by numeric fields - but it's probably 
the easiest and most general way to proceed.

A difficulty with this approach is that if a type already supports the == 
and != operators then, to retain backwards compatibility, the existing 
rules would need to apply to those operators which might be inconsistent 
with comparison using 'stringified' values. However, you could still work 
around this difficulty by replacing these operators with (for example) the 
following combinations when an ordering operation (as opposed to a 
comparison operation) was being performed:

Instead of x == y, use (x >= y && x <= y)
Instead of x != y, use (x > y || x < y)

An advantage of this approach is that it might still be useful outside 
generic contexts.

What do you guys think of this idea? I apologize if it's already been 
suggested by someone else but I'm losing track of what has been suggested 
in this area.

Alan

-- 
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