Jon_Shier
(Jon Shier)
January 15, 2018, 10:30pm
1
Swifters:
Take this simple Point type:
struct Point: Hashable {
let x: Int
let y: Int
init(_ x: Int, _ y: Int) {
self.x = x
self.y = y
}
}
Using the latest Swift 4.1 snapshot, the Hashable conformance is generated for me. Adding Comparable conformance like this:
extension Point: Comparable {
static func < (lhs: Point, rhs: Point) -> Bool {
return (lhs.x < rhs.x && lhs.y <= rhs.y) || (lhs.x <= rhs.x && lhs.y < rhs.y)
}
}
Once this is implemented, (0, 2) <= (1,1) bizarrely evaluates as true, despite both < and == evaluating as false. Manually implementing <= fixes the issue.
static func <= (lhs: Point, rhs: Point) -> Bool {
return lhs < rhs || lhs == rhs
}
This is pretty straightforward code, so am I missing something here?
Jon
gribozavr
(Dmitri Gribenko)
January 16, 2018, 1:38am
2
This is pretty straightforward code, so am I missing something here?
Your '<' function does not define a valid strict total order.
For
let p1 = Point(1, 1)
let p2 = Point(0, 2)
neither of 'p1 < p2', 'p2 < p1', 'p1 == p2' is true. This is the root cause.
static func <= (lhs: Point, rhs: Point) -> Bool {
return lhs < rhs || lhs == rhs
}
A faster way to compute it (with only one call to a user-defined
comparison operator) is to return '!(rhs < lhs)', which is wat the
standard library does, which is why you see the behavior that you are
seeing.
Dmitri
···
On Mon, Jan 15, 2018 at 2:30 PM, Jon Shier via swift-users <swift-users@swift.org> wrote:
--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/
1 Like
Jon_Shier
(Jon Shier)
January 16, 2018, 4:07am
3
Thanks Dmitri. Once I looked up the total ordering for points I was able to get proper behavior.
static func < (lhs: Point, rhs: Point) -> Bool {
return lhs.x < rhs.x || (lhs.x == rhs.x && lhs.y < rhs.y)
}
Jon
···
On Jan 15, 2018, at 8:38 PM, Dmitri Gribenko <gribozavr@gmail.com> wrote:
On Mon, Jan 15, 2018 at 2:30 PM, Jon Shier via swift-users > <swift-users@swift.org> wrote:
This is pretty straightforward code, so am I missing something here?
Your '<' function does not define a valid strict total order.
For
let p1 = Point(1, 1)
let p2 = Point(0, 2)
neither of 'p1 < p2', 'p2 < p1', 'p1 == p2' is true. This is the root cause.
static func <= (lhs: Point, rhs: Point) -> Bool {
return lhs < rhs || lhs == rhs
}
A faster way to compute it (with only one call to a user-defined
comparison operator) is to return '!(rhs < lhs)', which is wat the
standard library does, which is why you see the behavior that you are
seeing.
Dmitri
--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/