<div dir="ltr">Hi Pyry,<div>thanks for all the work you have put into this!</div><div>Could you please explain for someone as simple minded as me why there is (or has to be) a difference in the implementation of <, <= and >, >=?</div><div>Sorry, but I don't get into my head why there is/has to be a preference for one side. Could you or someone else point out (in the proposal) why there is a need/what is the reason for this?</div><div>I assume that this might not be obvious to some other people on the first look, too.</div><div><br></div><div>Björn </div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Jul 25, 2016 at 1:41 PM, Pyry Jahkola via swift-evolution <span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word">Since we're running short on time, and the previous discussion thread diverged, here's my attempt to fix the Comparable protocol.<div><br></div><div><b>Pull request:</b> <a href="https://github.com/apple/swift-evolution/pull/464" target="_blank">https://github.com/apple/swift-evolution/pull/464</a></div><div><div><br></div><div>TL;DR:</div><div><br></div><div>1. Equatable remains unchanged, while Comparable bloats a bit to support several use cases.</div><div>2. `a <=> b` is well-defined even if either value is NaN. Zero is equal to minus zero.</div><div>3. Types are not strictly required to become totally ordered, even if it's strongly recommended.</div><div><br></div><div>— — —</div><div><br></div><div>I simply can't see how a pure total order version of Comparable would fit the standard way floating point values are expected to behave. However, I think we can reach a satisfactory conclusion, one that involves no crashing in the standard library, which is what I previously suggested.</div><div><br></div><div>What I'm trying to fix is so that all operations listed in <a href="https://dl.dropboxusercontent.com/u/217402/Comparable.pdf" target="_blank">https://dl.dropboxusercontent.com/u/217402/Comparable.pdf</a> abide to laws for types without incomparable values, and that types with weaker order can still work in <i>some</i> well-defined way outside their totally ordered range.<br><div><div><br></div><div>PS. Forgive me Robert, Jaden, and Harlan for not syncing with you, for time is tight. I can pull back or revise the proposal if you don't want to be involved.</div></div></div><div><br></div><div>— Pyry</div><div><br></div><div><br></div><div><br></div><div><br></div><div><h1 style="margin-right:0px;margin-bottom:16px;margin-left:0px;line-height:1.25;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';background-color:rgb(255,255,255);margin-top:0px!important">Formalized Ordering</h1><ul style="padding-left:2em;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)"><li>Proposal: <a href="https://github.com/pyrtsa/swift-evolution/blob/ca89e7b3a1dffc99baa695a03544fcba75afd0f3/proposals/NNNN-filename.md" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">SE-NNNN</a></li><li style="margin-top:0.25em">Authors: <a href="https://github.com/codafi" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">Robert Widmann</a>, <a href="https://github.com/jadengeller" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">Jaden Geller</a>, <a href="https://github.com/harlanhaskins" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">Harlan Haskins</a>, <a href="https://github.com/pyrtsa" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">Pyry Jahkola</a></li><li style="margin-top:0.25em">Status: <span style="font-weight:600">Awaiting review</span></li><li style="margin-top:0.25em">Review manager: TBD</li></ul><h2 style="margin-top:24px;margin-bottom:16px;line-height:1.25;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';background-color:rgb(255,255,255)"><a href="https://github.com/pyrtsa/swift-evolution/blob/ca89e7b3a1dffc99baa695a03544fcba75afd0f3/proposals/NNNN-formalized-ordering.md#introduction" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;float:left;padding-right:4px;line-height:1" target="_blank"><u></u><u></u><u></u><u></u></a>Introduction</h2><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">This proposal cleans up the semantics of ordering relations in the standard library. Our goal is to formalize the total ordering semantics of the <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable</code> protocol and still provide accessible ordering definitions for types without total ordering semantics.</p><h2 style="margin-top:24px;margin-bottom:16px;line-height:1.25;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';background-color:rgb(255,255,255)"><a href="https://github.com/pyrtsa/swift-evolution/blob/ca89e7b3a1dffc99baa695a03544fcba75afd0f3/proposals/NNNN-formalized-ordering.md#motivation" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;float:left;padding-right:4px;line-height:1" target="_blank"><u></u><u></u><u></u><u></u></a>Motivation</h2><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">The standard comparison operators have an intuitive meaning to programmers. Swift encourages encoding that in an implementation of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable</code> that respects the rules of a <a href="https://en.wikipedia.org/wiki/Total_order" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">total order</a>. The standard library takes advantage of these rules to provide consistent implementations for sorting and searching generic collections of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable</code> types.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">Not all types behave so well in this framework, unfortunately. There are cases where the semantics of a total order cannot apply and still maintain the traditional definition of “comparison” over these types. Take, for example, sorting an array of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Float</code> s. Today, <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Float</code> ‘s instance of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable</code> follows IEEE-754 and returns <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">false</code> for all comparisons of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NaN</code> . In order to sort this array, <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NaN</code> s are considered outside the domain of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px"><</code> , and the order of a “sorted” array containing them is undefined.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">In addition, generic algorithms in the Swift Standard Library that make use of the current <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable</code> protocol may have to make twice as many comparisons to request the ordering of values with respect to each other than they should. Having a central operation to return information about the ordering of values once should provide a speedup for these operations.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">In the interest of cleaning up the semantics of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable</code> types of all shapes and sizes and their uses in the Swift Standard Library, this proposal is going to re-arrange the requirements of the <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable</code> and <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Equatable</code> protocols.</p><h2 style="margin-top:24px;margin-bottom:16px;line-height:1.25;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';background-color:rgb(255,255,255)"><a href="https://github.com/pyrtsa/swift-evolution/blob/ca89e7b3a1dffc99baa695a03544fcba75afd0f3/proposals/NNNN-formalized-ordering.md#proposed-solution" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;float:left;padding-right:4px;line-height:1" target="_blank"><u></u><u></u><u></u><u></u></a>Proposed solution</h2><h3 style="margin-top:24px;margin-bottom:16px;font-size:1.25em;line-height:1.25;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';background-color:rgb(255,255,255)"><a href="https://github.com/pyrtsa/swift-evolution/blob/ca89e7b3a1dffc99baa695a03544fcba75afd0f3/proposals/NNNN-formalized-ordering.md#equatable" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;float:left;padding-right:4px;line-height:1" target="_blank"><u></u><u></u><u></u><u></u></a>Equatable</h3><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">The interface of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Equatable</code> remains unchanged under this proposal. Equatable types should still respect the equivalence laws of <em>reflexivity</em> (<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">a == a</code>), <em>symmetry</em> (<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">a == b</code> iff <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">b == a</code>), and <em>transitivity</em> (if <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">a == b</code> and <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">b == c</code>, then <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">a == c</code>). Further, <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">!=</code> remains a top-level binary operator for which <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">a != b</code> iff <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">!(a == b)</code>.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">Types containing properties <em>inessential to equality</em>, however, are allowed to retain their notion of identity. For example <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Array</code>'s <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">capacity</code> isn't considered for equality; and <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">-0.0 == 0.0</code> and <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">"ä" == "a\u{308}"</code>, while <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">(-0.0).sign != (0.0).sign</code> and <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">"ä".utf8.count != "a\u{308}".utf8.count</code>.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">IEEE-754 floating point numbers are allowed to break the reflexivity law by defining that <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">.nan != x</code> for any value of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">x</code>, which is the standard behaviour documented in IEEE-754 and implemented the same way in other programming languages.</p><h3 style="margin-top:24px;margin-bottom:16px;font-size:1.25em;line-height:1.25;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';background-color:rgb(255,255,255)"><a href="https://github.com/pyrtsa/swift-evolution/blob/ca89e7b3a1dffc99baa695a03544fcba75afd0f3/proposals/NNNN-formalized-ordering.md#comparable" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;float:left;padding-right:4px;line-height:1" target="_blank"><u></u><u></u><u></u><u></u></a>Comparable</h3><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">The <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable</code> protocol will now require (without default implementation provided) a single operator definition: <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px"><=></code> — the comparison operator. From this, all other comparison operators will be derived so as to respect the total order semantics of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable</code>:</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">To maintain compatibility with IEEE-754, the interface of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable</code> also contains as customization points the operators <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px"><</code>, <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px"><=</code>, and <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">==</code> (derived from <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Equatable</code>) as well as the static binary functions <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">_min(_:_:)</code> and <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">_max(_:_:)</code>. User-defined types are recommended against overriding the default implementations.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">The uncustomizable top-level binary comparison operators <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">a > b</code> and <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">a >= b</code> are implemented as synonyms to <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">b < a</code>and <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">b <= a</code>, respectively.</p><h3 style="margin-top:24px;margin-bottom:16px;font-size:1.25em;line-height:1.25;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';background-color:rgb(255,255,255)"><a href="https://github.com/pyrtsa/swift-evolution/blob/ca89e7b3a1dffc99baa695a03544fcba75afd0f3/proposals/NNNN-formalized-ordering.md#standard-library" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;float:left;padding-right:4px;line-height:1" target="_blank"><u></u><u></u><u></u><u></u></a>Standard Library</h3><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">Unlike a previous revision of this proposal, standard library algorithms specific to <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">FloatingPoint</code> remain unchanged.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">Overloads of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px"><=></code> for tuples of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable</code> elements are provided up to a library-defined arity.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">The intent of this proposal is to later augment the standard library so that functions that take an ordering predicate <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">by: (T, T) -> Bool</code> will have an overload <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">ordering: (T, T) -> Ordering</code> that will provide a — potentially — more efficient implementation. A list of such functions is provided in Future directions.</p><h2 style="margin-top:24px;margin-bottom:16px;line-height:1.25;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';background-color:rgb(255,255,255)"><a href="https://github.com/pyrtsa/swift-evolution/blob/ca89e7b3a1dffc99baa695a03544fcba75afd0f3/proposals/NNNN-formalized-ordering.md#detailed-design" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;float:left;padding-right:4px;line-height:1" target="_blank"><u></u><u></u><u></u><u></u></a>Detailed design</h2><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">The <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable</code> protocol will be amended by taking away <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">></code> and <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">>=</code>, adding customisation points <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">_min(_:_:)</code>, and <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">_max(_:_:)</code>, and introducing the ordering operator <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px"><=></code> that makes use of the <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Ordering</code> enum defined below.</p><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)"><pre style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">enum</span> Ordering <span style="color:rgb(167,29,93)">:</span> <span style="color:rgb(0,134,179)">Equatable</span> {
<span style="color:rgb(167,29,93)">case</span> ascending
<span style="color:rgb(167,29,93)">case</span> equal
<span style="color:rgb(167,29,93)">case</span> descending
}
<span style="color:rgb(167,29,93)">infix</span> <span style="color:rgb(167,29,93)">operator</span> <span style="color:rgb(167,29,93)"><=></span> { <span style="color:rgb(167,29,93)">associativity</span> <span style="color:rgb(167,29,93)">none</span> <span style="color:rgb(167,29,93)">precedence</span> <span style="color:rgb(0,134,179)">130</span> }
<span style="color:rgb(167,29,93)">public</span> <span style="color:rgb(167,29,93)">protocol</span> <span style="color:rgb(0,134,179)">Comparable</span> <span style="color:rgb(167,29,93)">:</span> <span style="color:rgb(0,134,179)">Equatable</span> {
<span style="color:rgb(150,152,150)">// Implementation required:</span>
<span style="color:rgb(167,29,93)">static</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)"><=></span>(lhs: <span style="color:rgb(167,29,93)">Self</span>, rhs: <span style="color:rgb(167,29,93)">Self</span>) <span style="color:rgb(167,29,93)">-></span> Ordering
<span style="color:rgb(150,152,150)">// Default implementations provided:</span>
<span style="color:rgb(167,29,93)">static</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">==</span> (lhs: <span style="color:rgb(167,29,93)">Self</span>, rhs: <span style="color:rgb(167,29,93)">Self</span>) <span style="color:rgb(167,29,93)">-></span> <span style="color:rgb(0,134,179)">Bool</span> // derived from <span style="color:rgb(0,134,179)">Equatable</span>
<span style="color:rgb(167,29,93)">static</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)"><</span> (lhs: <span style="color:rgb(167,29,93)">Self</span>, rhs: <span style="color:rgb(167,29,93)">Self</span>) <span style="color:rgb(167,29,93)">-></span> <span style="color:rgb(0,134,179)">Bool</span>
<span style="color:rgb(167,29,93)">static</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)"><=</span> (lhs: <span style="color:rgb(167,29,93)">Self</span>, rhs: <span style="color:rgb(167,29,93)">Self</span>) <span style="color:rgb(167,29,93)">-></span> <span style="color:rgb(0,134,179)">Bool</span>
<span style="color:rgb(167,29,93)">static</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">_min</span>(<span style="color:rgb(121,93,163)">_</span> <span>lhs</span>: <span style="color:rgb(167,29,93)">Self</span>, <span style="color:rgb(121,93,163)">_</span> <span>rhs</span>: <span style="color:rgb(167,29,93)">Self</span>) <span style="color:rgb(167,29,93)">-></span> Self
<span style="color:rgb(167,29,93)">static</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">_max</span>(<span style="color:rgb(121,93,163)">_</span> <span>lhs</span>: <span style="color:rgb(167,29,93)">Self</span>, <span style="color:rgb(121,93,163)">_</span> <span>rhs</span>: <span style="color:rgb(167,29,93)">Self</span>) <span style="color:rgb(167,29,93)">-></span> Self
}</pre></div><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">The <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px"><=></code> operator defines a relationship between <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">==</code> and <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px"><=></code> such that <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">a == b</code> iff <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">(a <=> b) == .equal</code>, unless <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Self</code> chooses to break the semantics in the way of IEEE-754. Likewise, it should hold that <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">(a <=> b) == .ascending</code> iff <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">a < b</code>, and <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">(a <=> b) != .descending</code> iff <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">a <= b</code>.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">The <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">_min(_:_:)</code> and <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">_max(_:_:)</code> functions should return the lesser or greater of the two operands, respectively, while in case of equal arguments, <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">_min(_:_:)</code> should favour the left-hand side and <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">_max(_:_:)</code> the right-hand side to retain identity, as presently explained in <a href="https://github.com/apple/swift/blob/4614adc16168d612b6fc7e7a161dd5b6b34be704/stdlib/public/core/Algorithm.swift#L17-L20" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">this comment</a>. Making them customization points of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable</code>, we get to fix their behaviour in the presense of unorderable values (<a href="https://bugs.swift.org/browse/SR-1011" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">SR-1011</a>).</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">Most user types should only implement <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px"><=></code> and leave the other members of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Equatable</code> and <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable</code> to their default implementations. Note that even <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">==</code> has a sane default implementation if <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Self</code> is made <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable</code>:</p><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)"><pre style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(150,152,150)">// Default implementations, which should be used for most Comparable types:</span>
<span style="color:rgb(167,29,93)">extension</span> <span style="color:rgb(0,134,179)">Comparable</span> {
<span style="color:rgb(167,29,93)">static</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">==</span> (l: <span style="color:rgb(167,29,93)">Self</span>, r: <span style="color:rgb(167,29,93)">Self</span>) <span style="color:rgb(167,29,93)">-></span> <span style="color:rgb(0,134,179)">Bool</span> { <span style="color:rgb(167,29,93)">return</span> (l <span style="color:rgb(167,29,93)"><=></span> r) <span style="color:rgb(167,29,93)">==</span> <span style="color:rgb(167,29,93)">.</span>equal }
<span style="color:rgb(167,29,93)">static</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)"><</span> (l: <span style="color:rgb(167,29,93)">Self</span>, r: <span style="color:rgb(167,29,93)">Self</span>) <span style="color:rgb(167,29,93)">-></span> <span style="color:rgb(0,134,179)">Bool</span> { <span style="color:rgb(167,29,93)">return</span> (l <span style="color:rgb(167,29,93)"><=></span> r) <span style="color:rgb(167,29,93)">==</span> <span style="color:rgb(167,29,93)">.</span>ascending }
<span style="color:rgb(167,29,93)">static</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)"><=</span> (l: <span style="color:rgb(167,29,93)">Self</span>, r: <span style="color:rgb(167,29,93)">Self</span>) <span style="color:rgb(167,29,93)">-></span> <span style="color:rgb(0,134,179)">Bool</span> { <span style="color:rgb(167,29,93)">return</span> (l <span style="color:rgb(167,29,93)"><=></span> r) <span style="color:rgb(167,29,93)">!=</span> <span style="color:rgb(167,29,93)">.</span>descending }
<span style="color:rgb(167,29,93)">static</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">_min</span>(<span style="color:rgb(121,93,163)">_</span> <span>l</span>: <span style="color:rgb(167,29,93)">Self</span>, <span style="color:rgb(121,93,163)">_</span> <span>r</span>: <span style="color:rgb(167,29,93)">Self</span>) <span style="color:rgb(167,29,93)">-></span> Self { <span style="color:rgb(167,29,93)">return</span> r <span style="color:rgb(167,29,93)"><</span> l <span style="color:rgb(167,29,93)">?</span> r <span style="color:rgb(167,29,93)">:</span> l }
<span style="color:rgb(167,29,93)">static</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">_max</span>(<span style="color:rgb(121,93,163)">_</span> <span>l</span>: <span style="color:rgb(167,29,93)">Self</span>, <span style="color:rgb(121,93,163)">_</span> <span>r</span>: <span style="color:rgb(167,29,93)">Self</span>) <span style="color:rgb(167,29,93)">-></span> Self { <span style="color:rgb(167,29,93)">return</span> r <span style="color:rgb(167,29,93)"><</span> l <span style="color:rgb(167,29,93)">?</span> l <span style="color:rgb(167,29,93)">:</span> r }
}
<span style="color:rgb(150,152,150)">// Unoverridable top-level operators and functions for Comparable:</span>
<span style="color:rgb(167,29,93)">public</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">></span> <T <span style="color:rgb(167,29,93)">:</span> <span style="color:rgb(0,134,179)">Comparable</span>>(l: T, r: T) <span style="color:rgb(167,29,93)">-></span> <span style="color:rgb(0,134,179)">Bool</span> { <span style="color:rgb(167,29,93)">return</span> r <span style="color:rgb(167,29,93)"><</span> l }
<span style="color:rgb(167,29,93)">public</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">>=</span> <T <span style="color:rgb(167,29,93)">:</span> <span style="color:rgb(0,134,179)">Comparable</span>>(l: T, r: T) <span style="color:rgb(167,29,93)">-></span> <span style="color:rgb(0,134,179)">Bool</span> { <span style="color:rgb(167,29,93)">return</span> r <span style="color:rgb(167,29,93)"><=</span> l }
<span style="color:rgb(167,29,93)">public</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">min</span><T <span style="color:rgb(167,29,93)">:</span> <span style="color:rgb(0,134,179)">Comparable</span>>(<span style="color:rgb(121,93,163)">_</span> <span>l</span>: T, <span style="color:rgb(121,93,163)">_</span> <span>r</span>: T) <span style="color:rgb(167,29,93)">-></span> T { <span style="color:rgb(167,29,93)">return</span> T<span style="color:rgb(167,29,93)">.</span>_min(l, r) }
<span style="color:rgb(167,29,93)">public</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">max</span><T <span style="color:rgb(167,29,93)">:</span> <span style="color:rgb(0,134,179)">Comparable</span>>(<span style="color:rgb(121,93,163)">_</span> <span>l</span>: T, <span style="color:rgb(121,93,163)">_</span> <span>r</span>: T) <span style="color:rgb(167,29,93)">-></span> T { <span style="color:rgb(167,29,93)">return</span> T<span style="color:rgb(167,29,93)">.</span>_max(l, r) }</pre></div><h3 style="margin-top:24px;margin-bottom:16px;font-size:1.25em;line-height:1.25;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';background-color:rgb(255,255,255)"><a href="https://github.com/pyrtsa/swift-evolution/blob/ca89e7b3a1dffc99baa695a03544fcba75afd0f3/proposals/NNNN-formalized-ordering.md#handling-of-floating-point-comparisons" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;float:left;padding-right:4px;line-height:1" target="_blank"><u></u><u></u><u></u><u></u></a>Handling of floating point comparisons</h3><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)"><em>The following text is written in terms of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Double</code> but other floating-point types (<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Float</code>, <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Float80</code>) are proposed the same treatment.</em></p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">The IEEE-754 floating point specification has two oddities when it comes to orderability: there are two zeros (<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">0.0</code> and <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">-0.0</code>) which are considered equal to each other, and there are <em>multiple</em> not-a-number values <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">x</code> for which <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">x.isNaN == true</code> and <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">x != y</code> with any value of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">y</code>, even <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">x</code> itself. (Remark: the most common NaN value is obtained by the static property <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Double.nan</code>.)</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">The interface of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable</code> is designed so that <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px"><=></code> alone is able to produce a total order among all possible <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Double</code>values, sorting negative NaNs less than any other values, and positive NaNs greater than any other. Otherwise, within the range of totally ordered floating point values, <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">-Double.infinity ... Double.infinity</code>, the result of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">a <=> b</code> remains in full agreement with the laws of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">a < b</code>, <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">a <= b</code>, and <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">a == b</code>.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">The suggested implementation of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Double : Comparable</code> makes <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px"><=></code> distinguish between every different <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">bitPattern</code>of NaN:</p><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)"><pre style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">extension</span> <span style="color:rgb(0,134,179)">Double</span> <span style="color:rgb(167,29,93)">:</span> <span style="color:rgb(0,134,179)">Comparable</span> {
<span style="color:rgb(167,29,93)">public</span> <span style="color:rgb(167,29,93)">static</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)"><=></span> (l: <span style="color:rgb(0,134,179)">Double</span>, r: <span style="color:rgb(0,134,179)">Double</span>) <span style="color:rgb(167,29,93)">-></span> Ordering {
<span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">ordinal</span>(<span style="color:rgb(121,93,163)">_</span> <span>x</span>: <span style="color:rgb(0,134,179)">UInt64</span>) <span style="color:rgb(167,29,93)">-></span> <span style="color:rgb(0,134,179)">UInt64</span> {
<span style="color:rgb(167,29,93)">return</span> x <span style="color:rgb(167,29,93)"><</span> 0x80000000_00000000 <span style="color:rgb(167,29,93)">?</span> x <span style="color:rgb(167,29,93)">+</span> 0x7fffffff_ffffffff <span style="color:rgb(167,29,93)">:</span> <span style="color:rgb(167,29,93)">~</span>x
}
<span style="color:rgb(167,29,93)">return</span> ordinal(l<span style="color:rgb(167,29,93)">.</span>bitPattern) <span style="color:rgb(167,29,93)"><=></span> ordinal(r<span style="color:rgb(167,29,93)">.</span>bitPattern)
}
<span style="color:rgb(167,29,93)">public</span> <span style="color:rgb(167,29,93)">static</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">==</span> (l: <span style="color:rgb(0,134,179)">Double</span>, r: <span style="color:rgb(0,134,179)">Double</span>) <span style="color:rgb(167,29,93)">-></span> <span style="color:rgb(0,134,179)">Bool</span> { <span style="color:rgb(167,29,93)">return</span> Builtin<span style="color:rgb(167,29,93)">.</span>eq(l, r) }
<span style="color:rgb(167,29,93)">public</span> <span style="color:rgb(167,29,93)">static</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)"><</span> (l: <span style="color:rgb(0,134,179)">Double</span>, r: <span style="color:rgb(0,134,179)">Double</span>) <span style="color:rgb(167,29,93)">-></span> <span style="color:rgb(0,134,179)">Bool</span> { <span style="color:rgb(167,29,93)">return</span> Builtin<span style="color:rgb(167,29,93)">.</span>lt(l, r) }
<span style="color:rgb(167,29,93)">public</span> <span style="color:rgb(167,29,93)">static</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)"><=</span> (l: <span style="color:rgb(0,134,179)">Double</span>, r: <span style="color:rgb(0,134,179)">Double</span>) <span style="color:rgb(167,29,93)">-></span> <span style="color:rgb(0,134,179)">Bool</span> { <span style="color:rgb(167,29,93)">return</span> Builtin<span style="color:rgb(167,29,93)">.</span>le(l, r) }
<span style="color:rgb(167,29,93)">public</span> <span style="color:rgb(167,29,93)">static</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">_min</span>(l: <span style="color:rgb(0,134,179)">Double</span>, r: <span style="color:rgb(0,134,179)">Double</span>) <span style="color:rgb(167,29,93)">-></span> <span style="color:rgb(0,134,179)">Double</span> { <span style="color:rgb(167,29,93)">return</span> Builtin<span style="color:rgb(167,29,93)">.</span>fmin(l, r) }
<span style="color:rgb(167,29,93)">public</span> <span style="color:rgb(167,29,93)">static</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">_max</span>(l: <span style="color:rgb(0,134,179)">Double</span>, r: <span style="color:rgb(0,134,179)">Double</span>) <span style="color:rgb(167,29,93)">-></span> <span style="color:rgb(0,134,179)">Double</span> { <span style="color:rgb(167,29,93)">return</span> Builtin<span style="color:rgb(167,29,93)">.</span>fmax(l, r) }
}
<span style="color:rgb(150,152,150)">// Likewise:</span>
<span style="color:rgb(167,29,93)">extension</span> <span style="color:rgb(0,134,179)">Float</span> <span style="color:rgb(167,29,93)">:</span> <span style="color:rgb(0,134,179)">Comparable</span> { <span style="color:rgb(167,29,93)">...</span> }
<span style="color:rgb(167,29,93)">extension</span> <span style="color:rgb(0,134,179)">Float80</span> <span style="color:rgb(167,29,93)">:</span> <span style="color:rgb(0,134,179)">Comparable</span> { <span style="color:rgb(167,29,93)">...</span> }</pre></div><h3 style="margin-top:24px;margin-bottom:16px;font-size:1.25em;line-height:1.25;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';background-color:rgb(255,255,255)"><a href="https://github.com/pyrtsa/swift-evolution/blob/ca89e7b3a1dffc99baa695a03544fcba75afd0f3/proposals/NNNN-formalized-ordering.md#tuples-and-order-reversal" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;float:left;padding-right:4px;line-height:1" target="_blank"><u></u><u></u><u></u><u></u></a>Tuples and order reversal</h3><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">Due to missing language support, tuples of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable</code> elements cannot be <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable</code> themselves, but in the spirit of <a href="https://github.com/apple/swift-evolution/blob/master/proposals/0015-tuple-comparison-operators.md" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">SE-0015</a>, such tuples are given their overloads of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px"><=></code> up to a standard library defined maximum arity:</p><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)"><pre style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">public</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)"><=></span> <A <span style="color:rgb(167,29,93)">:</span> <span style="color:rgb(0,134,179)">Comparable</span>, B <span style="color:rgb(167,29,93)">:</span> <span style="color:rgb(0,134,179)">Comparable</span>>(lhs: (A, B), rhs: (A, B)) <span style="color:rgb(167,29,93)">-></span> Ordering {
<span style="color:rgb(167,29,93)">let</span> a <span style="color:rgb(167,29,93)">=</span> lhs<span style="color:rgb(167,29,93)">.</span><span style="color:rgb(0,134,179)">0</span> <span style="color:rgb(167,29,93)"><=></span> rhs<span style="color:rgb(167,29,93)">.</span><span style="color:rgb(0,134,179)">0</span>
<span style="color:rgb(167,29,93)">if</span> a <span style="color:rgb(167,29,93)">!=</span> <span style="color:rgb(167,29,93)">.</span>equal { <span style="color:rgb(167,29,93)">return</span> a }
<span style="color:rgb(167,29,93)">let</span> b <span style="color:rgb(167,29,93)">=</span> lhs<span style="color:rgb(167,29,93)">.</span><span style="color:rgb(0,134,179)">1</span> <span style="color:rgb(167,29,93)"><=></span> rhs<span style="color:rgb(167,29,93)">.</span><span style="color:rgb(0,134,179)">1</span>
<span style="color:rgb(167,29,93)">if</span> b <span style="color:rgb(167,29,93)">!=</span> <span style="color:rgb(167,29,93)">.</span>equal { <span style="color:rgb(167,29,93)">return</span> b }
<span style="color:rgb(167,29,93)">return</span> <span style="color:rgb(167,29,93)">.</span>equal
}
<span style="color:rgb(150,152,150)">// Similarly for <A : Comparable, B : Comparable, C : Comparable>, etc.</span></pre></div><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">To simplify the reversal of a given ordering operation, two members of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Ordering</code> are provided in an extension:</p><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)"><pre style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">extension</span> Ordering {
<span style="color:rgb(167,29,93)">public</span> <span style="color:rgb(167,29,93)">static</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">reversing</span><T <span style="color:rgb(167,29,93)">:</span> <span style="color:rgb(0,134,179)">Comparable</span>>(<span style="color:rgb(121,93,163)">_</span> <span>ordering</span>: (T, T) <span style="color:rgb(167,29,93)">-></span> Ordering)
<span style="color:rgb(167,29,93)">-></span> (T, T) <span style="color:rgb(167,29,93)">-></span> Ordering
{
<span style="color:rgb(167,29,93)">return</span> { l, r <span style="color:rgb(167,29,93)">in</span> ordering(r, l) }
}
<span style="color:rgb(167,29,93)">public</span> <span style="color:rgb(167,29,93)">var</span> reversed: Ordering {
<span style="color:rgb(167,29,93)">switch</span> <span style="color:rgb(167,29,93)">self</span> {
<span style="color:rgb(167,29,93)">case</span> <span style="color:rgb(167,29,93)">.</span>ascending: <span style="color:rgb(167,29,93)">return</span> <span style="color:rgb(167,29,93)">.</span>descending
<span style="color:rgb(167,29,93)">case</span> <span style="color:rgb(167,29,93)">.</span>equal: <span style="color:rgb(167,29,93)">return</span> <span style="color:rgb(167,29,93)">.</span>equal
<span style="color:rgb(167,29,93)">case</span> <span style="color:rgb(167,29,93)">.</span>descending: <span style="color:rgb(167,29,93)">return</span> <span style="color:rgb(167,29,93)">.</span>ascending
}
}
}</pre></div><h3 style="margin-top:24px;margin-bottom:16px;font-size:1.25em;line-height:1.25;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';background-color:rgb(255,255,255)"><a href="https://github.com/pyrtsa/swift-evolution/blob/ca89e7b3a1dffc99baa695a03544fcba75afd0f3/proposals/NNNN-formalized-ordering.md#foundation" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;float:left;padding-right:4px;line-height:1" target="_blank"><u></u><u></u><u></u><u></u></a>Foundation</h3><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">In addition, <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Foundation</code> code will now bridge <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSComparisonResult</code> to <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Ordering</code> allowing for a fluid, natural, and safe API.</p><h2 style="margin-top:24px;margin-bottom:16px;line-height:1.25;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';background-color:rgb(255,255,255)"><a href="https://github.com/pyrtsa/swift-evolution/blob/ca89e7b3a1dffc99baa695a03544fcba75afd0f3/proposals/NNNN-formalized-ordering.md#impact-on-existing-code" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;float:left;padding-right:4px;line-height:1" target="_blank"><u></u><u></u><u></u><u></u></a>Impact on existing code</h2><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">The biggest drawback of the proposed design is the large surface area of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable</code>'s interface, as well as the possibility of overriding the comparison operators by mistake. On the other hand, since the required <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px"><=></code> operator is new and affects all users porting their previously <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable</code> data types to Swift 3, we can use documentation to suggest removing the redundant (and possibly faulty) implementations of other comparison operators.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">Existing <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Equatable</code> but <span style="font-weight:600">not</span> <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable</code> types that define an equivalence relation with <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">==</code> will remain unchanged.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">Existing <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable</code> types that define a total ordering with <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px"><</code> will need to implement <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px"><=></code> and should remove their existing implementation of any comparison operators, including <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">==</code>. All other existing <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable</code> types should implement <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px"><=></code> that provides a total ordering, or should drop their <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable</code> conformance.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">Before:</p><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)"><pre style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">struct</span> Date: <span style="color:rgb(0,134,179)">Comparable</span> {
<span style="color:rgb(167,29,93)">let</span> year: <span style="color:rgb(0,134,179)">Int</span>
<span style="color:rgb(167,29,93)">let</span> month: <span style="color:rgb(0,134,179)">Int</span>
<span style="color:rgb(167,29,93)">let</span> day: <span style="color:rgb(0,134,179)">Int</span>
}
<span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">==</span>(lhs: Date, rhs: Date) <span style="color:rgb(167,29,93)">-></span> <span style="color:rgb(0,134,179)">Bool</span> {
<span style="color:rgb(167,29,93)">return</span> lhs<span style="color:rgb(167,29,93)">.</span>year <span style="color:rgb(167,29,93)">==</span> rhs<span style="color:rgb(167,29,93)">.</span>year
<span style="color:rgb(167,29,93)">&&</span> lhs<span style="color:rgb(167,29,93)">.</span>month <span style="color:rgb(167,29,93)">==</span> rhs<span style="color:rgb(167,29,93)">.</span>month
<span style="color:rgb(167,29,93)">&&</span> lhs<span style="color:rgb(167,29,93)">.</span>day <span style="color:rgb(167,29,93)">==</span> rhs<span style="color:rgb(167,29,93)">.</span>day
}
<span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)"><</span>(lhs: Date, rhs: Date) <span style="color:rgb(167,29,93)">-></span> <span style="color:rgb(0,134,179)">Bool</span> {
<span style="color:rgb(167,29,93)">if</span> lhs<span style="color:rgb(167,29,93)">.</span>year <span style="color:rgb(167,29,93)">!=</span> rhs<span style="color:rgb(167,29,93)">.</span>year {
<span style="color:rgb(167,29,93)">return</span> lhs<span style="color:rgb(167,29,93)">.</span>year <span style="color:rgb(167,29,93)"><</span> rhs<span style="color:rgb(167,29,93)">.</span>year
} <span style="color:rgb(167,29,93)">else</span> <span style="color:rgb(167,29,93)">if</span> lhs<span style="color:rgb(167,29,93)">.</span>month <span style="color:rgb(167,29,93)">!=</span> rhs<span style="color:rgb(167,29,93)">.</span>month {
<span style="color:rgb(167,29,93)">return</span> lhs<span style="color:rgb(167,29,93)">.</span>month <span style="color:rgb(167,29,93)"><</span> rhs<span style="color:rgb(167,29,93)">.</span>month
} <span style="color:rgb(167,29,93)">else</span> {
<span style="color:rgb(167,29,93)">return</span> lhs<span style="color:rgb(167,29,93)">.</span>day <span style="color:rgb(167,29,93)"><</span> rhs<span style="color:rgb(167,29,93)">.</span>day
}
}</pre></div><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">After, using the tuple overload of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px"><=></code>:</p><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)"><pre style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">struct</span> Date: <span style="color:rgb(0,134,179)">Comparable</span> {
<span style="color:rgb(167,29,93)">let</span> year: <span style="color:rgb(0,134,179)">Int</span>
<span style="color:rgb(167,29,93)">let</span> month: <span style="color:rgb(0,134,179)">Int</span>
<span style="color:rgb(167,29,93)">let</span> day: <span style="color:rgb(0,134,179)">Int</span>
<span style="color:rgb(167,29,93)">static</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)"><=></span> (lhs: Date, rhs: Date) <span style="color:rgb(167,29,93)">-></span> Ordering {
<span style="color:rgb(167,29,93)">return</span> (lhs<span style="color:rgb(167,29,93)">.</span>year, lhs<span style="color:rgb(167,29,93)">.</span>month, lhs<span style="color:rgb(167,29,93)">.</span>day)
<span style="color:rgb(167,29,93)"><=></span> (rhs<span style="color:rgb(167,29,93)">.</span>year, rhs<span style="color:rgb(167,29,93)">.</span>month, rhs<span style="color:rgb(167,29,93)">.</span>day)
}
<span style="color:rgb(150,152,150)">// // Explicit version:</span>
<span style="color:rgb(150,152,150)">// static func <=> (lhs: Date, rhs: Date) -> Ordering {</span>
<span style="color:rgb(150,152,150)">// let yearResult = lhs.year <=> rhs.year</span>
<span style="color:rgb(150,152,150)">// guard case .equal = yearResult else { return yearResult }</span>
<span style="color:rgb(150,152,150)">// let monthResult = lhs.month <=> rhs.month</span>
<span style="color:rgb(150,152,150)">// guard case .equal = monthResult else { return monthResult }</span>
<span style="color:rgb(150,152,150)">// return lhs.day <=> rhs.day</span>
<span style="color:rgb(150,152,150)">// }</span>
}</pre></div><h2 style="margin-top:24px;margin-bottom:16px;line-height:1.25;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';background-color:rgb(255,255,255)"><a href="https://github.com/pyrtsa/swift-evolution/blob/ca89e7b3a1dffc99baa695a03544fcba75afd0f3/proposals/NNNN-formalized-ordering.md#alternatives-considered" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;float:left;padding-right:4px;line-height:1" target="_blank"><u></u><u></u><u></u><u></u></a>Alternatives considered</h2><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">A previous design of this proposal suggested a strict total order upon <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable</code>. While that would make generic algorithms more correct, the definition ended up fighting against the expected behaviour of floating point numbers.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">An alternative design that better matches the existing arithmetic-related protocols in Swift is one that uses a member function.</p><div style="margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)"><pre style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">public</span> <span style="color:rgb(167,29,93)">protocol</span> <span style="color:rgb(0,134,179)">Comparable</span>: <span style="color:rgb(0,134,179)">Equatable</span> {
<span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">compare</span>(to: <span style="color:rgb(167,29,93)">Self</span>) <span style="color:rgb(167,29,93)">-></span> Ordering
}</pre></div><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">However, while this API does read better than an operator, we believe that this imposes a number of artificial restrictions (especially in light of <a href="https://github.com/apple/swift-evolution/blob/master/proposals/0091-improving-operators-in-protocols.md" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">SE-0091</a>)</p><ol style="padding-left:2em;margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)"><li>There is no way to use <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable.compare</code> as a higher-order function in a non-generic context.</li><li style="margin-top:0.25em">If a member is desired, it can be provided in a protocol extension and defined in terms of the ordering operator; to each according to their need.</li><li style="margin-top:0.25em">The existing tuple overloads cannot be expressed with a member function.</li></ol><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">One other that Rust has adopted is the inclusion of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">PartialEquatable</code> and <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">PartialComparable</code> as ancestors of their flavor of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Equatable</code> and <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Comparable</code> . Having protocols to organize and catalogue types that can only guarantee partial equivalence and ordering relations is a good approach for modularity but clutters the standard library with two new protocols for which few useful algorithms could be written against.</p><h2 style="margin-top:24px;margin-bottom:16px;line-height:1.25;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';background-color:rgb(255,255,255)"><a href="https://github.com/pyrtsa/swift-evolution/blob/ca89e7b3a1dffc99baa695a03544fcba75afd0f3/proposals/NNNN-formalized-ordering.md#future-directions" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;float:left;padding-right:4px;line-height:1" target="_blank"><u></u><u></u><u></u><u></u></a>Future directions</h2><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">That the default <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">sort()</code> compares by <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px"><</code> and not <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px"><=></code> should be considered a bug to be fixed in a future version of Swift. Using <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px"><=></code> will make <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">sort()</code> well-behaved in the presense of NaN. However, given that the current behaviour is to produce an unspecified order, the fix is additive and can be slipped past Swift 3.</p><p style="margin-top:0px;margin-bottom:16px;color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255)">With <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px"><=></code> in place, several present and future standard library algorithms involving a <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px"><T : Comparable></code> requirement will possibly benefit from knowing the total ordering of two operands at once. This is a list of possible such functions (taking <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">Array</code> as example), to be proposed separately as an additive change:</p><div style="color:rgb(51,51,51);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;background-color:rgb(255,255,255);margin-bottom:0px!important"><pre style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal"><span style="color:rgb(167,29,93)">extension</span> <span style="color:rgb(0,134,179)">Array</span> {
<span style="color:rgb(150,152,150)">// Sorting</span>
<span style="color:rgb(167,29,93)">mutating</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">sort</span>(ordering: <span style="color:rgb(167,29,93)">@noescape</span> (Element, Element) throws <span style="color:rgb(167,29,93)">-></span> Ordering) rethrows
<span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">sorted</span>(ordering: <span style="color:rgb(167,29,93)">@noescape</span> (Element, Element) throws <span style="color:rgb(167,29,93)">-></span> Ordering) rethrows -> [Element]
<span style="color:rgb(167,29,93)">mutating</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">stableSort</span>(ordering: <span style="color:rgb(167,29,93)">@noescape</span> (Element, Element) throws <span style="color:rgb(167,29,93)">-></span> Ordering) rethrows
<span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">stableSorted</span>(ordering: <span style="color:rgb(167,29,93)">@noescape</span> (Element, Element) throws <span style="color:rgb(167,29,93)">-></span> Ordering) rethrows -> [Element]
<span style="color:rgb(150,152,150)">/// Reorders the elements of the collection such that all the elements</span>
<span style="color:rgb(150,152,150)">/// returning `.ascending` are moved to the start of the collection, and the</span>
<span style="color:rgb(150,152,150)">/// elements returning `.descending` are moved to the end of the collection.</span>
<span style="color:rgb(150,152,150)">/// - Returns: the range of elements for which `ordering(x) == .equal`.</span>
<span style="color:rgb(167,29,93)">mutating</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">partition</span>(ordering: <span style="color:rgb(167,29,93)">@noescape</span> (Iterator<span style="color:rgb(167,29,93)">.</span>Element) throws <span style="color:rgb(167,29,93)">-></span> Ordering) rethrows -> <span style="color:rgb(0,134,179)">Range</span><Index>
<span style="color:rgb(150,152,150)">// Binary search</span>
<span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">bisectedIndex</span>(ordering: <span style="color:rgb(167,29,93)">@noescape</span> (Element) throws <span style="color:rgb(167,29,93)">-></span> Ordering) rethrows -> Index?
<span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">lowerBound</span>(ordering: <span style="color:rgb(167,29,93)">@noescape</span> (Element) throws <span style="color:rgb(167,29,93)">-></span> Ordering) rethrows -> Index
<span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">upperBound</span>(ordering: <span style="color:rgb(167,29,93)">@noescape</span> (Element) throws <span style="color:rgb(167,29,93)">-></span> Ordering) rethrows -> Index
<span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">equalRange</span>(ordering: <span style="color:rgb(167,29,93)">@noescape</span> (Element) throws <span style="color:rgb(167,29,93)">-></span> Ordering) rethrows -> <span style="color:rgb(0,134,179)">Range</span><Index>
}</pre></div><div><br></div></div></div></div><br>_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
<br></blockquote></div><br></div>