[Idea] Switching Comparable types: a new operator


(Ross O'Brien) #1

Compare two values, and react differently if the first is larger, the
second is larger, or they are equal.

An if statement will result in an 'if { } else if { } else { }' structure.
A switch can be used (case _ where x < y) but the compiler will complain
that the switch is not exhaustive, resulting in a redundant 'default' case.

I'd like to propose this addition to the Comparable type:

infix operator <=> {}

func <=> <C : Comparable> (lhs: C, rhs:C) -> NSComparisonResult

{

if lhs == rhs

{

return .OrderedSame

}

if lhs < rhs

{

return .OrderedAscending

}

return .OrderedDescending

}

This now allows code like this:

let x = 3

let y = 4

switch x <=> y

{

case .OrderedSame:

print(3)

case .OrderedAscending:

print(4)

case .OrderedDescending:

print(5)

}

-- Ross


(Jonathan Tang) #2

Can't you define this yourself? This worked in a Playground using Swift
2.1:

enum Ordering {
    case OrderedSame, OrderedAscending, OrderedDescending
}

infix operator <=> {}
func <=> <T: Comparable>(x: T, y: T) -> Ordering {
    if x < y {
        return .OrderedAscending
    } else if x > y {
        return .OrderedDescending
    } else {
        return .OrderedSame
    }
}

let x = 3
let y = 4
switch x <=> y {
case .OrderedSame:
    print(3)
case .OrderedAscending:
    print(4) // Executed
case .OrderedDescending:
    print(5)
}

···

On Thu, Feb 4, 2016 at 12:52 PM, Ross O'Brien via swift-evolution < swift-evolution@swift.org> wrote:

Compare two values, and react differently if the first is larger, the
second is larger, or they are equal.

An if statement will result in an 'if { } else if { } else { }' structure.
A switch can be used (case _ where x < y) but the compiler will complain
that the switch is not exhaustive, resulting in a redundant 'default' case.

I'd like to propose this addition to the Comparable type:

infix operator <=> {}

func <=> <C : Comparable> (lhs: C, rhs:C) -> NSComparisonResult

{

if lhs == rhs

{

return .OrderedSame

}

if lhs < rhs

{

return .OrderedAscending

}

return .OrderedDescending

}

This now allows code like this:

let x = 3

let y = 4

switch x <=> y

{

case .OrderedSame:

print(3)

case .OrderedAscending:

print(4)

case .OrderedDescending:

print(5)

}

-- Ross

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Dave Abrahams) #3

The problem is that the stdlib algorithms don't use this, so sorting,
e.g., an array of arrays of strings ends up being more expensive than
necessary. What you really want is for the "spaceship operator" to be
the primary implementation hook that gets called from the comparison
predicates.

It's on the agenda for swift 3 to add the spaceship operator, and make
the algorithms use it, and solve the migration problems for old code,
and solve the interop problems with foundation. However, we have a lot
of other work on our hands, and there's always a chance we won't fit it
in the schedule. This could make a great after-starter project for
someone out there who wanted to take it on (hint, hint).

···

on Thu Feb 04 2016, Jonathan Tang <swift-evolution@swift.org> wrote:

Can't you define this yourself? This worked in a Playground using Swift
2.1:

enum Ordering {
    case OrderedSame, OrderedAscending, OrderedDescending
}

infix operator <=> {}
func <=> <T: Comparable>(x: T, y: T) -> Ordering {
    if x < y {
        return .OrderedAscending
    } else if x > y {
        return .OrderedDescending
    } else {
        return .OrderedSame
    }
}

let x = 3
let y = 4
switch x <=> y {
case .OrderedSame:
    print(3)
case .OrderedAscending:
    print(4) // Executed
case .OrderedDescending:
    print(5)
}

--
-Dave


(Ross O'Brien) #4

In answer to Jonathan:
I can define it myself - and did, in the original post. I don't know how
common a use-case it is, but it's a small annoyance with switch statements
to write 'default: break // this is impossible'. This is a specific
scenario where case pattern-matching pattern seemed inadequate, so I pitch
it here for more discussion, my thinking being that: perhaps if it's in
Core, it can be implemented more efficiently than I've done here. Perhaps
there are better choices of characters for the specific operator. Perhaps
there's a reason why converting this comparison into an NSComparisonResult
isn't already there. I only find out if I ask!

In answer to Dave:
That's interesting to hear (and possibly saved everyone the bother of a
review!). I wasn't aware it was already a named operator (and in use in
other languages, now I've looked it up). I hope it makes it into the
schedule, as I'm not sure I know enough to take on that hint!

···

On Fri, Feb 5, 2016 at 12:10 AM, Dave Abrahams via swift-evolution < swift-evolution@swift.org> wrote:

on Thu Feb 04 2016, Jonathan Tang <swift-evolution@swift.org> wrote:

> Can't you define this yourself? This worked in a Playground using Swift
> 2.1:
>
> enum Ordering {
> case OrderedSame, OrderedAscending, OrderedDescending
> }
>
> infix operator <=> {}
> func <=> <T: Comparable>(x: T, y: T) -> Ordering {
> if x < y {
> return .OrderedAscending
> } else if x > y {
> return .OrderedDescending
> } else {
> return .OrderedSame
> }
> }
>
> let x = 3
> let y = 4
> switch x <=> y {
> case .OrderedSame:
> print(3)
> case .OrderedAscending:
> print(4) // Executed
> case .OrderedDescending:
> print(5)
> }

The problem is that the stdlib algorithms don't use this, so sorting,
e.g., an array of arrays of strings ends up being more expensive than
necessary. What you really want is for the "spaceship operator" to be
the primary implementation hook that gets called from the comparison
predicates.

It's on the agenda for swift 3 to add the spaceship operator, and make
the algorithms use it, and solve the migration problems for old code,
and solve the interop problems with foundation. However, we have a lot
of other work on our hands, and there's always a chance we won't fit it
in the schedule. This could make a great after-starter project for
someone out there who wanted to take it on (hint, hint).

--
-Dave

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution