Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-25 Thread Dave Abrahams via swift-evolution

on Sun Jul 24 2016, Brent Royal-Gordon  wrote:

>> On Jul 24, 2016, at 9:06 PM, Pyry Jahkola via swift-evolution
>  wrote:
>> 
>> Another possible choice would be to return .descending whenever
>> either of the comparands were NaN, while also making <, >, <=, and
>> >= return false in such cases. Then we wouldn't see
>> preconditionFailures but instead produced bogus results from sort,
>> partition etc. That's the tradeoff Haskell has chosen for its
>> `compare` function over Double, FWIW.
>
> That's essentially what we currently have. I think we'd like to fix
> it.
>
> Honestly, I think the most natural result is that calls like `sort()`
> and `max()` ignore NaNs—for instance, an Array might have
> fewer elements if you sort it. 

That would be deeply surprising and would create a programming model
that was almost impossible to work with.  I could not support a result
like that.

> That seems to be the behavior implied by
> `FloatingPoint.maximum/minimum(_:_:)`. 

That elements are dropped from a collection when it is sorted?  How do
you figure?

> However, it is still possible to access and use the total ordering if
> you need it.
>
> This sort of suggests we should have two levels of comparisons:
>
> * `===` and `<===>` are total.
>
> * `==` and `<=>` may not work on, or may conflate, some values.

This has really gone off the rails, guys.  There are no generic
algorithms that rely on an under-all-circumstances-substitutability
property, so we shouldn't encode it into a protocol.

Also, think about what “under all circumstances” really means: it means
that there are no implementation details, because it is possible for
code with access rights to inspect them.  It means that no class
instances can ever be substitutable for other instances, because of
ObjectIdentity.  It becomes absurd really quickly.

> How to actually accomplish this is a more difficult question. The
> simplest solution might be something like:
>
>   protocol Equatable {
>   static func === (…) -> Bool
>   static func == (…) -> Bool
>   }
>   extension Equatable {
>   static func == (…) -> Bool {
>   return lhs === rhs
>   }
>   }
>
>   protocol Comparable: Equatable {
>   /// Total ordering which works on and distinguishes
> between all values of the type.
>   static func <===> (…) -> Ordering
>
>   /// "Friendly" ordering which may conflate or not work
> on some values of the type.
>   /// 
>   /// - Precondition: Neither `lhs` nor `rhs` returns
> `true` from `isAberration`.
>   static func <=> (…) -> Ordering
>
>   /// If true, this instance should be ignored when
> using the <=> operator.
>   var isAberration: Bool { get }
>   }
>   extension Comparable {
>   static func === (…) -> Bool {
>   return (lhs <===> rhs) == .same
>   }
>   static func == (…) -> Bool {
>   return (lhs <=> rhs) == .same
>   }
>   static func <=> (…) -> Ordering {
>   return lhs <===> rhs
>   }
>   var isAberration: Bool {
>   return true
>   }
>   }
>
> However, this means that sorting requires two functions, not one (or
> that, when using a custom sorting function, you must separately
> pre-filter the aberrations from your data set). An alternative would
> be to introduce a PartialOrdering type:
>
>   enum PartialOrdering {
>   case ordered (Ordering)
>   case leftUnordered
>   case bothUnordered
>   case rightUnordered
>   }
>   // As above, except...
>   protocol Comparable: Equatable {
>   ...
>
>   /// "Friendly" ordering which may not work on some
> values of the type.
>   /// 
>   /// - Precondition: Neither `lhs` nor `rhs` returns
> `true` from `isAberration`.
>   static func <=> (…) -> PartialOrdering
>   }
>
> This wouldn't necessarily handle the `-0.0 == +0.0` case well,
> though. That *could* be handled with extra cases meaning "equal but
> ordered", but this is looking messier and messier.

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


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-25 Thread Xiaodi Wu via swift-evolution
On Mon, Jul 25, 2016 at 1:12 AM, Brent Royal-Gordon via swift-evolution <
swift-evolution@swift.org> wrote:

> > On Jul 24, 2016, at 9:06 PM, Pyry Jahkola via swift-evolution <
> swift-evolution@swift.org> wrote:
> >
> > Another possible choice would be to return .descending whenever either
> of the comparands were NaN, while also making <, >, <=, and >= return false
> in such cases. Then we wouldn't see preconditionFailures but instead
> produced bogus results from sort, partition etc. That's the tradeoff
> Haskell has chosen for its `compare` function over Double, FWIW.
>
> That's essentially what we currently have. I think we'd like to fix it.
>
> Honestly, I think the most natural result is that calls like `sort()` and
> `max()` ignore NaNs—for instance, an Array might have fewer
> elements if you sort it. That seems to be the behavior implied by
> `FloatingPoint.maximum/minimum(_:_:)`. However, it is still possible to
> access and use the total ordering if you need it.
>
> This sort of suggests we should have two levels of comparisons:
>
> * `===` and `<===>` are total.
>
> * `==` and `<=>` may not work on, or may conflate, some values.
>

Agreed very much. Although, any "friendly" `<=>` can be derived from what
you call `<===>` and `==`.

I've been playing with a variation where I have a "friendly" equivalence
relation `==?` (returns `Bool?` so that it's `nil` when there's a argument
that doesn't make sense to compare) and a finer equivalence relation `===`
as protocol requirements on Equatable, with a generic `==` defined as `{
return (lhs ==? rhs) ?? (lhs === rhs) }`. In that model, traditional
comparison operators can be synthesized from a total ordering (which you
call `<===>` and the original proposal calls `<=>`) by first consulting the
value of the friendly `==?` to determine if two operands are the same.

How to actually accomplish this is a more difficult question. The simplest
> solution might be something like:
>
> protocol Equatable {
> static func === (…) -> Bool
> static func == (…) -> Bool
> }
> extension Equatable {
> static func == (…) -> Bool {
> return lhs === rhs
> }
> }
>
> protocol Comparable: Equatable {
> /// Total ordering which works on and distinguishes
> between all values of the type.
> static func <===> (…) -> Ordering
>
> /// "Friendly" ordering which may conflate or not work on
> some values of the type.
> ///
> /// - Precondition: Neither `lhs` nor `rhs` returns `true`
> from `isAberration`.
> static func <=> (…) -> Ordering
>
> /// If true, this instance should be ignored when using
> the <=> operator.
> var isAberration: Bool { get }
> }
> extension Comparable {
> static func === (…) -> Bool {
> return (lhs <===> rhs) == .same
> }
> static func == (…) -> Bool {
> return (lhs <=> rhs) == .same
> }
> static func <=> (…) -> Ordering {
> return lhs <===> rhs
> }
> var isAberration: Bool {
> return true
> }
> }
>
> However, this means that sorting requires two functions, not one (or that,
> when using a custom sorting function, you must separately pre-filter the
> aberrations from your data set). An alternative would be to introduce a
> PartialOrdering type:
>
>
> enum PartialOrdering {
> case ordered (Ordering)
> case leftUnordered
> case bothUnordered
> case rightUnordered
> }
> // As above, except...
> protocol Comparable: Equatable {
> ...
>
> /// "Friendly" ordering which may not work on some values
> of the type.
> ///
> /// - Precondition: Neither `lhs` nor `rhs` returns `true`
> from `isAberration`.
> static func <=> (…) -> PartialOrdering
> }
>
> This wouldn't necessarily handle the `-0.0 == +0.0` case well, though.
> That *could* be handled with extra cases meaning "equal but ordered", but
> this is looking messier and messier.
>
> --
> Brent Royal-Gordon
> Architechies
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-25 Thread Brent Royal-Gordon via swift-evolution
> On Jul 24, 2016, at 9:06 PM, Pyry Jahkola via swift-evolution 
>  wrote:
> 
> Another possible choice would be to return .descending whenever either of the 
> comparands were NaN, while also making <, >, <=, and >= return false in such 
> cases. Then we wouldn't see preconditionFailures but instead produced bogus 
> results from sort, partition etc. That's the tradeoff Haskell has chosen for 
> its `compare` function over Double, FWIW.

That's essentially what we currently have. I think we'd like to fix it.

Honestly, I think the most natural result is that calls like `sort()` and 
`max()` ignore NaNs—for instance, an Array might have fewer elements if 
you sort it. That seems to be the behavior implied by 
`FloatingPoint.maximum/minimum(_:_:)`. However, it is still possible to access 
and use the total ordering if you need it.

This sort of suggests we should have two levels of comparisons:

* `===` and `<===>` are total.

* `==` and `<=>` may not work on, or may conflate, some values.

How to actually accomplish this is a more difficult question. The simplest 
solution might be something like:

protocol Equatable {
static func === (…) -> Bool
static func == (…) -> Bool
}
extension Equatable {
static func == (…) -> Bool {
return lhs === rhs
}
}

protocol Comparable: Equatable {
/// Total ordering which works on and distinguishes between all 
values of the type.
static func <===> (…) -> Ordering

/// "Friendly" ordering which may conflate or not work on some 
values of the type.
/// 
/// - Precondition: Neither `lhs` nor `rhs` returns `true` from 
`isAberration`.
static func <=> (…) -> Ordering

/// If true, this instance should be ignored when using the <=> 
operator.
var isAberration: Bool { get }
}
extension Comparable {
static func === (…) -> Bool {
return (lhs <===> rhs) == .same
}
static func == (…) -> Bool {
return (lhs <=> rhs) == .same
}
static func <=> (…) -> Ordering {
return lhs <===> rhs
}
var isAberration: Bool {
return true
}
}

However, this means that sorting requires two functions, not one (or that, when 
using a custom sorting function, you must separately pre-filter the aberrations 
from your data set). An alternative would be to introduce a PartialOrdering 
type:


enum PartialOrdering {
case ordered (Ordering)
case leftUnordered
case bothUnordered
case rightUnordered
}
// As above, except...
protocol Comparable: Equatable {
...

/// "Friendly" ordering which may not work on some values of 
the type.
/// 
/// - Precondition: Neither `lhs` nor `rhs` returns `true` from 
`isAberration`.
static func <=> (…) -> PartialOrdering
}

This wouldn't necessarily handle the `-0.0 == +0.0` case well, though. That 
*could* be handled with extra cases meaning "equal but ordered", but this is 
looking messier and messier.

-- 
Brent Royal-Gordon
Architechies

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


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-24 Thread Pyry Jahkola via swift-evolution

> Dave Abrahams wrote:
> 
> Asking whether zero appears in a sequence that happened to contain a NaN 
> would equally be a precondition violation.

No, it wouldn't because Double would implement Equatable + Comparable by 
providing custom implementations of ==, <, >, <=, and >=, in addition to 
Double.<=> which may trap.

My point in 
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160718/025375.html
 is that by keeping all those operators within the required interface of 
protocol Comparable, such customisation remains possible. The original proposal 
only suggested == in Equatable and <=> in Comparable. If that were the case, 
then generic algorithms would necessarily end up calling <=>.

It is key that not only <=> is a customisation point of Comparable. Only those 
generic algorithms which used <=> directly (e.g. sort, partition, binary 
search) would see precondition violations if the sequence contained one or more 
NaNs.

***

Another possible choice would be to return .descending whenever either of the 
comparands were NaN, while also making <, >, <=, and >= return false in such 
cases. Then we wouldn't see preconditionFailures but instead produced bogus 
results from sort, partition etc. That's the tradeoff Haskell has chosen for 
its `compare` function over Double, FWIW.

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


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-24 Thread Dave Abrahams via swift-evolution
Asking whether zero appears in a sequence that happened to contain a NaN would 
equally be a precondition violation. I don't think that's an acceptable cliff. 
The point of NaNs and Infs is that they flow through a multidimensional 
calculation without disturbing the parts that are still valid, rather than, 
e.g., 
trapping. 

Sent from my moss-covered three-handled family gradunza

> On Jul 24, 2016, at 10:40 AM, Pyry Jahkola  wrote:
> 
> Pyry Jahkola wrote:
> 
>>> or even to ask whether
>>> someSequence.contains(.nan).  IMO that's not really acceptable.
>> 
>> Not correct. Algorithms like contains(_:) or firstIndex(of:) would use the 
>> == operator which is part of the protocol and thus wouldn't call <=> on 
>> FloatingPoint types which override the default implementation.
> 
> Oops, spoke too soon. Well, I think it's easy enough to require people to 
> write numbers.contains(where: { $0.isNaN }) in this use case.
> 
> — Pyry
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-24 Thread Ben Rimmington via swift-evolution

> On 22 Jul 2016, at 18:43, Dave Abrahams wrote:
> 
>> on Fri Jul 22 2016, Haravikk  wrote:
>> 
>> In my own hacked implementation I'm using Order.before, Order.same,
>> and Order.after. It's not much of a change, but it seems to clarify
>> what the enum is, at least in my opinion.
> 
> I always thought the name “Order” would be perfect if it weren't so
> short and likely to conflict with type names that user code will want.
> We do have qualification to fall back on, so this is a judgement call.

enum TotalOrder {
  case ascending
  case identical
  case descending
}

-- Ben

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


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-24 Thread Pyry Jahkola via swift-evolution
Pyry Jahkola wrote:

>> or even to ask whether
>> someSequence.contains(.nan).  IMO that's not really acceptable.
> 
> Not correct. Algorithms like contains(_:) or firstIndex(of:) would use the == 
> operator which is part of the protocol and thus wouldn't call <=> on 
> FloatingPoint types which override the default implementation.

Oops, spoke too soon. Well, I think it's easy enough to require people to write 
numbers.contains(where: { $0.isNaN }) in this use case.

— Pyry
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-24 Thread Pyry Jahkola via swift-evolution
Dave Abrahams wrote:

>> Given all this, I propose a simpler model that makes `a <=> b` follow
>> the expected behaviour of < and ==, with the tradeoff that `a <=>
>> .nan` and `.nan <=> b` will abort with a precondition failure:
> 
> This effectively makes it a precondition violation to default-sort
> a sequence of floats that contains a NaN

Correct. I'm still pondering if that could be alleviated in this model with 
minor modifications. Note however, that the proposed IEEE 754 total order would 
put negative NaNs at front and positive NaNs at the end. I can't say that's too 
useful either.

> or even to ask whether
> someSequence.contains(.nan).  IMO that's not really acceptable.

Not correct. Algorithms like contains(_:) or firstIndex(of:) would use the == 
operator which is part of the protocol and thus wouldn't call <=> on 
FloatingPoint types which override the default implementation.

— Pyry

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


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-24 Thread Dave Abrahams via swift-evolution

on Sat Jul 23 2016, Xiaodi Wu  wrote:

> IMO what's causing the headaches now isn't NaN; it's actually +0 and
> -0.

Yes, and specifically division by zero, which *seriously doesn't concern
me*.  I view the reason for floating point's (1/0 == Inf) to be very
similar to its reason for having NaN, which I understand to be this:
practitioners want to do very large multivariate calculations where if
*some* of the results can't be computed, it doesn't scuttle all of them.
They also want to preserve as much information as possible about the
likely nature of results when precision limits come into play

When I read what mathematicians say about division by zero (e.g.
https://www.quora.com/Is-1-0-infinity/answer/Dan-Piponi and
https://www.quora.com/Is-1-0-infinity/answer/Michael-Lamar), it seems to
me that there is no well-defined answer, and we could view +Inf and -Inf
as the way floating point responds to a precondition violation.

I would *much* rather do a little handwaving in the area of division by
zero than in the areas of equivalence and ordering.

> On Sat, Jul 23, 2016 at 4:19 PM, Nevin Brackett-Rozinsky <
> nevin.brackettrozin...@gmail.com> wrote:
>
>> Another option would be to leave the IEEE 754 NaN hijinks in Float and
>> Double (as numerics people expect), and create a new type (with a nice
>> approachable name) that “acts like” Double but does not model NaN. Then any
>> operation which would ordinarily produce a NaN, instead traps for the new
>> type. That way its comparison operators only have to worry about non-NaN
>> values, which makes everything much cleaner.
>>
>> Sorting Doubles would retain its present functionality, warts and all,
>> which numerics people should be expected to handle. Whereas the new type
>> (“Number” sounds good, especially if we can make it subsume NSNumber) would
>> never have a NaN in the first place.
>>
>> Nevin
>>
>>
>>
>> On Sat, Jul 23, 2016 at 4:57 PM, Xiaodi Wu via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>> Sorry to overwhelm with more emails. I'd like to show some work and
>>> further analysis for your consideration that refines the sketch I just
>>> wrote:
>>>
>>> Two FP values a and b can be, with respect to each other:
>>>
>>> * ordered or unordered (per IEEE, NaN compares unordered to everything,
>>> including itself)
>>> * identical or not identical (for these purposes, we adopt Steve's
>>> proposed test for identity: substitutable for all operations; thus +0 is
>>> not identical to -0, but different binary representations of the same value
>>> are identical)
>>> * equal or not equal (i.e. the behavior of the == operator today)
>>>
>>> So, if a and b are, with respect to each other:
>>>
>>> * ordered, identical, equal -- this is what happens ordinarily with two
>>> equal, non-NaN values
>>> * ordered, identical, not equal -- this can never happen
>>> * ordered, not identical, equal -- only +0 and -0
>>> * ordered, not identical, not equal -- this is what happens ordinarily
>>> with two unequal, non-NaN values
>>>
>>> * unordered, identical, equal -- this can never happen, but if NaNs are
>>> to be well-behaved (for a true equivalence relation), then we will need an
>>> equivalence relation in which NaN == NaN
>>> * unordered, identical, not equal -- this is what always happens, but if
>>> NaNs are to be well-behaved, then such behavior will need to change
>>> * unordered, not identical, equal -- this can never happen
>>> * unordered, not identical, not equal -- this is what ordinarily happens
>>> with one NaN and one non-NaN value
>>>
>>> Equatable can have === and my proposed ==? as part of its protocol; a
>>> generic ==, as originally proposed, would be defined outside the protocol.
>>> A default implementation of ==? will forward to ===, and the generic ==
>>> will be defined as `{ return (lhs ==? rhs) ?? (lhs === rhs) }`.
>>> For floating point, ==? will be specialized and cease to forward to ===
>>> so that +0 and -0 compare true and NaN and anything compare nil, and
>>> floating point == will be defined notionally as `{ return (lhs ==? rhs) ??
>>> false }`.
>>>
>>>
>>> On Sat, Jul 23, 2016 at 3:09 PM, Xiaodi Wu  wrote:
>>>
 Throwing out some more radical ideas here. Suppose we had instead
 (taking inspiration from IEEE notation):

 [Pardon any errors; I'm writing freehand in Gmail]

 infix operator ==? { /* figure out precedence later */ }

 protocol Equatable {
   static func ==? (lhs: Self, rhs: Self) -> Bool?
   /* semantics:
  this function returns nil if lhs and rhs are unordered with respect
 to each other
  otherwise, evaluate by means of a legal equivalence relation */
 }

 func == (lhs: T, rhs: T) -> Bool {
   return (lhs ==? rhs) ?? false
 }

 protocol Comparable : Equatable {
   static func <=> (lhs: Self, rhs: Self) -> Ordering
   /* semantics:
  this is a total ordering; thus:
  if `(a 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-24 Thread Dave Abrahams via swift-evolution

on Sat Jul 23 2016, Pyry Jahkola  wrote:

> Given all this, I propose a simpler model that makes `a <=> b` follow
> the expected behaviour of < and ==, with the tradeoff that `a <=>
> .nan` and `.nan <=> b` will abort with a precondition failure:

This effectively makes it a precondition violation to default-sort
a sequence of floats that contains a NaN or even to ask whether
someSequence.contains(.nan).  IMO that's not really acceptable.

> 1) We keep the current Interface of Equatable unchanged, with !=
> defined in terms of ==.
>
> 2) Comparable would still refine Equatable, and include all the
> comparison operators, adding the new <=>:
>
> protocol Comparable : Equatable {
>   static func <=>(lhs: Self, rhs: Self) -> Ordering
>   static func <(lhs: Self, rhs: Self) -> Bool
>   static func >(lhs: Self, rhs: Self) -> Bool
>   static func <=(lhs: Self, rhs: Self) -> Bool
>   static func >=(lhs: Self, rhs: Self) -> Bool
> }
>
> The comparison operators are kept in the interface so that partially
> ordered types such as Double can be supported in generic
> code. However, the documentation should recommend against defining `<`
> manually.
>
> 3) Default implementations for  are provided for
> the following operators: ==, <, >, <=, and >=.
>
> 4) User-defined types will need to define just <=> to conform to
> Comparable. (Even == can be omitted!)
>
> 5) FloatingPoint types implement custom versions of ==, <, >, <=, and
>>= using the standard IEEE 754 definition (i.e. comparisons involving
> NaN return false). Zero is zero; `0.0 == -0.0 && !(-0.0 < 0.0)` holds.
>
> 6) FloatingPoint types implement <=> as:
>
> func <=> (lhs: T, rhs: T) -> Ordering {
>   if lhs < rhs { return .ascending }
>   if rhs < lhs { return .descending }
>   precondition(lhs == rhs)
>   return .same
> }
>
> 7) Algorithms using <=> directly should mention so in their
> documentation as a precondition that they require total order between
> elements. Many generic algorithms can be defined in terms of == or <,
> and should.
>
> If we took the oroginally planned route that distinguished between
> identities such as -0.0 vs. +0.0, or between the 2⁴⁹ - 2 ≈ 5.6 × 10¹⁴
> possible NaN values that Double has, 

I agree that our default ordering and equivalence tests should not
consider these differences to be essential/salient.

> we'd also need to consider other oddballs like the difference and
> ordering between the Strings "ä" and "a\u{308}", which are considered
> equal but produce a different Unicode representation. I think it's
> best to hide those identities behind another interface than Equatable
> and Comparable, and let the protocols serve more mundane application
> logic.
>
> — Pyry
>
>> Dave Abrahams wrote:
>> 
>> 
>>> on Sat Jul 23 2016, Xiaodi Wu  wrote:
>>> 
>>> On Fri, Jul 22, 2016 at 11:34 PM, Stephen Canon  wrote:
>>> 
> The point of this design is that `===` means identity and that `.same `
> also means identity.
> 
> Since this is new territory I suppose we get to decide what identity
> means for floating point.  Should +0 and -0 have the same identity or
> not?  I’ll leave the answer to folks more knowledgable about numerics
> than I.
 
 Boy, I take my wife out for a movie and come back to 50 new messages on SE.
 
 I need to read the entire thread more carefully, but off the top of my
 head, I think that `-0 === +0` is False.  If we’re going to have an
 `isSame` / `isIdentical` / whatever it's called, I would expect it to imply
 substitutability.  Although -0 == +0, they are not equivalent when
 substituted:
 
 - 1/(-0) != 1/0
 - Float(-0).sign != Float(+0).sign
 - etc
 
 This probably then implies that `<=>` is not `.same` either.  I’ll read
 the rest of this and respond more completely tomorrow.
>>> 
>>> Eagerly await your evaluation of the discussion. In the meantime:
>>> 
>>> I think Dave's view that `===` defines identity in terms of "essential"
>>> qualities implies that two identical values can be
>>> different/non-substitutable in "inessential" qualities. For generic
>>> purposes, the sign of zero could be one such inessential quality.
>> 
>> Yes, and I think our view of how people work with numbers in swift (and
>> their protocol conformances) reflect this approach.  
>> 
>> http://article.gmane.org/gmane.comp.lang.swift.evolution/16321
>> 
>> My sense is that we want to choose the default notions of identity and
>> ordering so as to support the way people think about these numeric
>> types, inexact though it may be.  Therefore, finding 0.0 in a sequence
>> of floats should succeed when the sequence contains -0.0, and a stable
>> sort on floating point keys should preserve the relative order of all
>> elements having +0.0 and -0.0 keys.  
>> 
>> People that want to work with inessential qualities such as the sign of
>> zero can always pass Float.totalOrdering 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-23 Thread Daniel Duan via swift-evolution


Daniel Duan
Sent from my iPhone

> On Jul 23, 2016, at 3:15 PM, Ross O'Brien via swift-evolution 
>  wrote:
> 
> This might be a radical suggestion ... or possibly a naive or unoriginal one, 
> I'll find out once I suggest it.
> 
> Swift took the bold step of establishing optionals as a central type, rather 
> than assigning dual meanings to 'default' values such as zero or false. 
> Recognising the concept of not having a value, and safeguarding against that, 
> is core to Swift.

Optional is nothing new or "bold". It's been main stream for years. Even C++ 
has it :)

> Is it possible for Swift to recognise that there are values which simply 
> aren't comparable, rather than forcing a choice between ascending, same, 
> descending? Could we add a fourth: incomparable?
> 

The problem we are trying to solve here is strict total ordering: 
https://en.m.wikipedia.org/wiki/Total_order

> What if a sort operation didn't simply return an array of ordered values? 
> What if it partitioned the values into comparable and incomparable values, 
> and returned a sorted array of the former and an unordered collection of the 
> latter?
> Maybe, this being Swift, we could use some kind of 'sort!' exclamation mark 
> to forcibly express that every value in the collection-to-be-sorted is 
> implicitly comparable, if we're sure.
> 
> 
>> On Sat, Jul 23, 2016 at 10:37 PM, Xiaodi Wu via swift-evolution 
>>  wrote:
>>> On Sat, Jul 23, 2016 at 4:19 PM, Nevin Brackett-Rozinsky 
>>>  wrote:
>>> Another option would be to leave the IEEE 754 NaN hijinks in Float and 
>>> Double (as numerics people expect), and create a new type (with a nice 
>>> approachable name) that “acts like” Double but does not model NaN. Then any 
>>> operation which would ordinarily produce a NaN, instead traps for the new 
>>> type. That way its comparison operators only have to worry about non-NaN 
>>> values, which makes everything much cleaner.
>>> 
>>> Sorting Doubles would retain its present functionality, warts and all, 
>>> which numerics people should be expected to handle. Whereas the new type 
>>> (“Number” sounds good, especially if we can make it subsume NSNumber) would 
>>> never have a NaN in the first place.
>> 
>> The other comment I would make here is that, as mentioned earlier by Pyry, 
>> there are other types for which we'll need to reckon with domain-specific 
>> "hijinks" that don't offer easy notions of identity, Unicode being one 
>> example. I'd expect that many types that model an existing domain of human 
>> endeavor will run into something like this. Thus, carefully working through 
>> a design for fundamental protocols like Equatable and Comparable that don't 
>> fall down with FP will prove more broadly fruitful. I don't think that 
>> segregating all hijinks and modeling what we *wish* the world to be is as 
>> beneficial in terms of allowing generic algorithms to work meaningfully with 
>> types that people actually use in real-world scenarios.
>>  
>>> Nevin
>>> 
>>> 
>>> 
 On Sat, Jul 23, 2016 at 4:57 PM, Xiaodi Wu via swift-evolution 
  wrote:
 Sorry to overwhelm with more emails. I'd like to show some work and 
 further analysis for your consideration that refines the sketch I just 
 wrote:
 
 Two FP values a and b can be, with respect to each other:
 
 * ordered or unordered (per IEEE, NaN compares unordered to everything, 
 including itself)
 * identical or not identical (for these purposes, we adopt Steve's 
 proposed test for identity: substitutable for all operations; thus +0 is 
 not identical to -0, but different binary representations of the same 
 value are identical)
 * equal or not equal (i.e. the behavior of the == operator today)
 
 So, if a and b are, with respect to each other:
 
 * ordered, identical, equal -- this is what happens ordinarily with two 
 equal, non-NaN values
 * ordered, identical, not equal -- this can never happen
 * ordered, not identical, equal -- only +0 and -0
 * ordered, not identical, not equal -- this is what happens ordinarily 
 with two unequal, non-NaN values
 
 * unordered, identical, equal -- this can never happen, but if NaNs are to 
 be well-behaved (for a true equivalence relation), then we will need an 
 equivalence relation in which NaN == NaN
 * unordered, identical, not equal -- this is what always happens, but if 
 NaNs are to be well-behaved, then such behavior will need to change
 * unordered, not identical, equal -- this can never happen
 * unordered, not identical, not equal -- this is what ordinarily happens 
 with one NaN and one non-NaN value
 
 Equatable can have === and my proposed ==? as part of its protocol; a 
 generic ==, as originally proposed, would be defined outside the protocol.
 A default 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-23 Thread Ross O'Brien via swift-evolution
This might be a radical suggestion ... or possibly a naive or unoriginal
one, I'll find out once I suggest it.

Swift took the bold step of establishing optionals as a central type,
rather than assigning dual meanings to 'default' values such as zero or
false. Recognising the concept of not having a value, and safeguarding
against that, is core to Swift.
Is it possible for Swift to recognise that there are values which simply
aren't comparable, rather than forcing a choice between ascending, same,
descending? Could we add a fourth: incomparable?

What if a sort operation didn't simply return an array of ordered values?
What if it *partitioned* the values into comparable and incomparable
values, and returned a sorted array of the former and an unordered
collection of the latter?
Maybe, this being Swift, we could use some kind of 'sort!' exclamation mark
to forcibly express that every value in the collection-to-be-sorted is
implicitly comparable, if we're sure.


On Sat, Jul 23, 2016 at 10:37 PM, Xiaodi Wu via swift-evolution <
swift-evolution@swift.org> wrote:

> On Sat, Jul 23, 2016 at 4:19 PM, Nevin Brackett-Rozinsky <
> nevin.brackettrozin...@gmail.com> wrote:
>
>> Another option would be to leave the IEEE 754 NaN hijinks in Float and
>> Double (as numerics people expect), and create a new type (with a nice
>> approachable name) that “acts like” Double but does not model NaN. Then any
>> operation which would ordinarily produce a NaN, instead traps for the new
>> type. That way its comparison operators only have to worry about non-NaN
>> values, which makes everything much cleaner.
>>
>> Sorting Doubles would retain its present functionality, warts and all,
>> which numerics people should be expected to handle. Whereas the new type
>> (“Number” sounds good, especially if we can make it subsume NSNumber) would
>> never have a NaN in the first place.
>>
>
> The other comment I would make here is that, as mentioned earlier by Pyry,
> there are other types for which we'll need to reckon with domain-specific
> "hijinks" that don't offer easy notions of identity, Unicode being one
> example. I'd expect that many types that model an existing domain of human
> endeavor will run into something like this. Thus, carefully working through
> a design for fundamental protocols like Equatable and Comparable that don't
> fall down with FP will prove more broadly fruitful. I don't think that
> segregating all hijinks and modeling what we *wish* the world to be is as
> beneficial in terms of allowing generic algorithms to work meaningfully
> with types that people actually use in real-world scenarios.
>
>
>> Nevin
>>
>>
>>
>> On Sat, Jul 23, 2016 at 4:57 PM, Xiaodi Wu via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>> Sorry to overwhelm with more emails. I'd like to show some work and
>>> further analysis for your consideration that refines the sketch I just
>>> wrote:
>>>
>>> Two FP values a and b can be, with respect to each other:
>>>
>>> * ordered or unordered (per IEEE, NaN compares unordered to everything,
>>> including itself)
>>> * identical or not identical (for these purposes, we adopt Steve's
>>> proposed test for identity: substitutable for all operations; thus +0 is
>>> not identical to -0, but different binary representations of the same value
>>> are identical)
>>> * equal or not equal (i.e. the behavior of the == operator today)
>>>
>>> So, if a and b are, with respect to each other:
>>>
>>> * ordered, identical, equal -- this is what happens ordinarily with two
>>> equal, non-NaN values
>>> * ordered, identical, not equal -- this can never happen
>>> * ordered, not identical, equal -- only +0 and -0
>>> * ordered, not identical, not equal -- this is what happens ordinarily
>>> with two unequal, non-NaN values
>>>
>>> * unordered, identical, equal -- this can never happen, but if NaNs are
>>> to be well-behaved (for a true equivalence relation), then we will need an
>>> equivalence relation in which NaN == NaN
>>> * unordered, identical, not equal -- this is what always happens, but if
>>> NaNs are to be well-behaved, then such behavior will need to change
>>> * unordered, not identical, equal -- this can never happen
>>> * unordered, not identical, not equal -- this is what ordinarily happens
>>> with one NaN and one non-NaN value
>>>
>>> Equatable can have === and my proposed ==? as part of its protocol; a
>>> generic ==, as originally proposed, would be defined outside the protocol.
>>> A default implementation of ==? will forward to ===, and the generic ==
>>> will be defined as `{ return (lhs ==? rhs) ?? (lhs === rhs) }`.
>>> For floating point, ==? will be specialized and cease to forward to ===
>>> so that +0 and -0 compare true and NaN and anything compare nil, and
>>> floating point == will be defined notionally as `{ return (lhs ==? rhs) ??
>>> false }`.
>>>
>>>
>>> On Sat, Jul 23, 2016 at 3:09 PM, Xiaodi Wu  wrote:
>>>
 Throwing out some more radical 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-23 Thread Xiaodi Wu via swift-evolution
On Sat, Jul 23, 2016 at 4:19 PM, Nevin Brackett-Rozinsky <
nevin.brackettrozin...@gmail.com> wrote:

> Another option would be to leave the IEEE 754 NaN hijinks in Float and
> Double (as numerics people expect), and create a new type (with a nice
> approachable name) that “acts like” Double but does not model NaN. Then any
> operation which would ordinarily produce a NaN, instead traps for the new
> type. That way its comparison operators only have to worry about non-NaN
> values, which makes everything much cleaner.
>
> Sorting Doubles would retain its present functionality, warts and all,
> which numerics people should be expected to handle. Whereas the new type
> (“Number” sounds good, especially if we can make it subsume NSNumber) would
> never have a NaN in the first place.
>

The other comment I would make here is that, as mentioned earlier by Pyry,
there are other types for which we'll need to reckon with domain-specific
"hijinks" that don't offer easy notions of identity, Unicode being one
example. I'd expect that many types that model an existing domain of human
endeavor will run into something like this. Thus, carefully working through
a design for fundamental protocols like Equatable and Comparable that don't
fall down with FP will prove more broadly fruitful. I don't think that
segregating all hijinks and modeling what we *wish* the world to be is as
beneficial in terms of allowing generic algorithms to work meaningfully
with types that people actually use in real-world scenarios.


> Nevin
>
>
>
> On Sat, Jul 23, 2016 at 4:57 PM, Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> Sorry to overwhelm with more emails. I'd like to show some work and
>> further analysis for your consideration that refines the sketch I just
>> wrote:
>>
>> Two FP values a and b can be, with respect to each other:
>>
>> * ordered or unordered (per IEEE, NaN compares unordered to everything,
>> including itself)
>> * identical or not identical (for these purposes, we adopt Steve's
>> proposed test for identity: substitutable for all operations; thus +0 is
>> not identical to -0, but different binary representations of the same value
>> are identical)
>> * equal or not equal (i.e. the behavior of the == operator today)
>>
>> So, if a and b are, with respect to each other:
>>
>> * ordered, identical, equal -- this is what happens ordinarily with two
>> equal, non-NaN values
>> * ordered, identical, not equal -- this can never happen
>> * ordered, not identical, equal -- only +0 and -0
>> * ordered, not identical, not equal -- this is what happens ordinarily
>> with two unequal, non-NaN values
>>
>> * unordered, identical, equal -- this can never happen, but if NaNs are
>> to be well-behaved (for a true equivalence relation), then we will need an
>> equivalence relation in which NaN == NaN
>> * unordered, identical, not equal -- this is what always happens, but if
>> NaNs are to be well-behaved, then such behavior will need to change
>> * unordered, not identical, equal -- this can never happen
>> * unordered, not identical, not equal -- this is what ordinarily happens
>> with one NaN and one non-NaN value
>>
>> Equatable can have === and my proposed ==? as part of its protocol; a
>> generic ==, as originally proposed, would be defined outside the protocol.
>> A default implementation of ==? will forward to ===, and the generic ==
>> will be defined as `{ return (lhs ==? rhs) ?? (lhs === rhs) }`.
>> For floating point, ==? will be specialized and cease to forward to ===
>> so that +0 and -0 compare true and NaN and anything compare nil, and
>> floating point == will be defined notionally as `{ return (lhs ==? rhs) ??
>> false }`.
>>
>>
>> On Sat, Jul 23, 2016 at 3:09 PM, Xiaodi Wu  wrote:
>>
>>> Throwing out some more radical ideas here. Suppose we had instead
>>> (taking inspiration from IEEE notation):
>>>
>>> [Pardon any errors; I'm writing freehand in Gmail]
>>>
>>> infix operator ==? { /* figure out precedence later */ }
>>>
>>> protocol Equatable {
>>>   static func ==? (lhs: Self, rhs: Self) -> Bool?
>>>   /* semantics:
>>>  this function returns nil if lhs and rhs are unordered with respect
>>> to each other
>>>  otherwise, evaluate by means of a legal equivalence relation */
>>> }
>>>
>>> func == (lhs: T, rhs: T) -> Bool {
>>>   return (lhs ==? rhs) ?? false
>>> }
>>>
>>> protocol Comparable : Equatable {
>>>   static func <=> (lhs: Self, rhs: Self) -> Ordering
>>>   /* semantics:
>>>  this is a total ordering; thus:
>>>  if `(a ==? b) == true`, then `(a <=> b) == .same`
>>>  if `(a ==? b) == false`, then `(a <=> b) != .same`
>>>  but, if `(a ==? b) == nil`, then `a <=> b` may yield any result
>>>   */
>>> }
>>>
>>>
>>> On Sat, Jul 23, 2016 at 2:35 PM, Pyry Jahkola 
>>> wrote:
>>>
 Given all this, I propose a simpler model that makes `a <=> b` follow
 the expected behaviour of < and ==, with the tradeoff that `a <=> 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-23 Thread Xiaodi Wu via swift-evolution
IMO what's causing the headaches now isn't NaN; it's actually +0 and -0.


On Sat, Jul 23, 2016 at 4:19 PM, Nevin Brackett-Rozinsky <
nevin.brackettrozin...@gmail.com> wrote:

> Another option would be to leave the IEEE 754 NaN hijinks in Float and
> Double (as numerics people expect), and create a new type (with a nice
> approachable name) that “acts like” Double but does not model NaN. Then any
> operation which would ordinarily produce a NaN, instead traps for the new
> type. That way its comparison operators only have to worry about non-NaN
> values, which makes everything much cleaner.
>
> Sorting Doubles would retain its present functionality, warts and all,
> which numerics people should be expected to handle. Whereas the new type
> (“Number” sounds good, especially if we can make it subsume NSNumber) would
> never have a NaN in the first place.
>
> Nevin
>
>
>
> On Sat, Jul 23, 2016 at 4:57 PM, Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> Sorry to overwhelm with more emails. I'd like to show some work and
>> further analysis for your consideration that refines the sketch I just
>> wrote:
>>
>> Two FP values a and b can be, with respect to each other:
>>
>> * ordered or unordered (per IEEE, NaN compares unordered to everything,
>> including itself)
>> * identical or not identical (for these purposes, we adopt Steve's
>> proposed test for identity: substitutable for all operations; thus +0 is
>> not identical to -0, but different binary representations of the same value
>> are identical)
>> * equal or not equal (i.e. the behavior of the == operator today)
>>
>> So, if a and b are, with respect to each other:
>>
>> * ordered, identical, equal -- this is what happens ordinarily with two
>> equal, non-NaN values
>> * ordered, identical, not equal -- this can never happen
>> * ordered, not identical, equal -- only +0 and -0
>> * ordered, not identical, not equal -- this is what happens ordinarily
>> with two unequal, non-NaN values
>>
>> * unordered, identical, equal -- this can never happen, but if NaNs are
>> to be well-behaved (for a true equivalence relation), then we will need an
>> equivalence relation in which NaN == NaN
>> * unordered, identical, not equal -- this is what always happens, but if
>> NaNs are to be well-behaved, then such behavior will need to change
>> * unordered, not identical, equal -- this can never happen
>> * unordered, not identical, not equal -- this is what ordinarily happens
>> with one NaN and one non-NaN value
>>
>> Equatable can have === and my proposed ==? as part of its protocol; a
>> generic ==, as originally proposed, would be defined outside the protocol.
>> A default implementation of ==? will forward to ===, and the generic ==
>> will be defined as `{ return (lhs ==? rhs) ?? (lhs === rhs) }`.
>> For floating point, ==? will be specialized and cease to forward to ===
>> so that +0 and -0 compare true and NaN and anything compare nil, and
>> floating point == will be defined notionally as `{ return (lhs ==? rhs) ??
>> false }`.
>>
>>
>> On Sat, Jul 23, 2016 at 3:09 PM, Xiaodi Wu  wrote:
>>
>>> Throwing out some more radical ideas here. Suppose we had instead
>>> (taking inspiration from IEEE notation):
>>>
>>> [Pardon any errors; I'm writing freehand in Gmail]
>>>
>>> infix operator ==? { /* figure out precedence later */ }
>>>
>>> protocol Equatable {
>>>   static func ==? (lhs: Self, rhs: Self) -> Bool?
>>>   /* semantics:
>>>  this function returns nil if lhs and rhs are unordered with respect
>>> to each other
>>>  otherwise, evaluate by means of a legal equivalence relation */
>>> }
>>>
>>> func == (lhs: T, rhs: T) -> Bool {
>>>   return (lhs ==? rhs) ?? false
>>> }
>>>
>>> protocol Comparable : Equatable {
>>>   static func <=> (lhs: Self, rhs: Self) -> Ordering
>>>   /* semantics:
>>>  this is a total ordering; thus:
>>>  if `(a ==? b) == true`, then `(a <=> b) == .same`
>>>  if `(a ==? b) == false`, then `(a <=> b) != .same`
>>>  but, if `(a ==? b) == nil`, then `a <=> b` may yield any result
>>>   */
>>> }
>>>
>>>
>>> On Sat, Jul 23, 2016 at 2:35 PM, Pyry Jahkola 
>>> wrote:
>>>
 Given all this, I propose a simpler model that makes `a <=> b` follow
 the expected behaviour of < and ==, with the tradeoff that `a <=> .nan` and
 `.nan <=> b` will abort with a precondition failure:

 1) We keep the current Interface of Equatable  unchanged, with !=
 defined in terms of ==.

 2) Comparable would still refine Equatable, and include all the
 comparison operators, adding the new <=>:

 protocol Comparable : Equatable {
   static func <=>(lhs: Self, rhs: Self) -> Ordering
   static func <(lhs: Self, rhs: Self) -> Bool
   static func >(lhs: Self, rhs: Self) -> Bool
   static func <=(lhs: Self, rhs: Self) -> Bool
   static func >=(lhs: Self, rhs: Self) -> Bool
 }

 The 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-23 Thread Nevin Brackett-Rozinsky via swift-evolution
Another option would be to leave the IEEE 754 NaN hijinks in Float and
Double (as numerics people expect), and create a new type (with a nice
approachable name) that “acts like” Double but does not model NaN. Then any
operation which would ordinarily produce a NaN, instead traps for the new
type. That way its comparison operators only have to worry about non-NaN
values, which makes everything much cleaner.

Sorting Doubles would retain its present functionality, warts and all,
which numerics people should be expected to handle. Whereas the new type
(“Number” sounds good, especially if we can make it subsume NSNumber) would
never have a NaN in the first place.

Nevin



On Sat, Jul 23, 2016 at 4:57 PM, Xiaodi Wu via swift-evolution <
swift-evolution@swift.org> wrote:

> Sorry to overwhelm with more emails. I'd like to show some work and
> further analysis for your consideration that refines the sketch I just
> wrote:
>
> Two FP values a and b can be, with respect to each other:
>
> * ordered or unordered (per IEEE, NaN compares unordered to everything,
> including itself)
> * identical or not identical (for these purposes, we adopt Steve's
> proposed test for identity: substitutable for all operations; thus +0 is
> not identical to -0, but different binary representations of the same value
> are identical)
> * equal or not equal (i.e. the behavior of the == operator today)
>
> So, if a and b are, with respect to each other:
>
> * ordered, identical, equal -- this is what happens ordinarily with two
> equal, non-NaN values
> * ordered, identical, not equal -- this can never happen
> * ordered, not identical, equal -- only +0 and -0
> * ordered, not identical, not equal -- this is what happens ordinarily
> with two unequal, non-NaN values
>
> * unordered, identical, equal -- this can never happen, but if NaNs are to
> be well-behaved (for a true equivalence relation), then we will need an
> equivalence relation in which NaN == NaN
> * unordered, identical, not equal -- this is what always happens, but if
> NaNs are to be well-behaved, then such behavior will need to change
> * unordered, not identical, equal -- this can never happen
> * unordered, not identical, not equal -- this is what ordinarily happens
> with one NaN and one non-NaN value
>
> Equatable can have === and my proposed ==? as part of its protocol; a
> generic ==, as originally proposed, would be defined outside the protocol.
> A default implementation of ==? will forward to ===, and the generic ==
> will be defined as `{ return (lhs ==? rhs) ?? (lhs === rhs) }`.
> For floating point, ==? will be specialized and cease to forward to === so
> that +0 and -0 compare true and NaN and anything compare nil, and floating
> point == will be defined notionally as `{ return (lhs ==? rhs) ?? false }`.
>
>
> On Sat, Jul 23, 2016 at 3:09 PM, Xiaodi Wu  wrote:
>
>> Throwing out some more radical ideas here. Suppose we had instead (taking
>> inspiration from IEEE notation):
>>
>> [Pardon any errors; I'm writing freehand in Gmail]
>>
>> infix operator ==? { /* figure out precedence later */ }
>>
>> protocol Equatable {
>>   static func ==? (lhs: Self, rhs: Self) -> Bool?
>>   /* semantics:
>>  this function returns nil if lhs and rhs are unordered with respect
>> to each other
>>  otherwise, evaluate by means of a legal equivalence relation */
>> }
>>
>> func == (lhs: T, rhs: T) -> Bool {
>>   return (lhs ==? rhs) ?? false
>> }
>>
>> protocol Comparable : Equatable {
>>   static func <=> (lhs: Self, rhs: Self) -> Ordering
>>   /* semantics:
>>  this is a total ordering; thus:
>>  if `(a ==? b) == true`, then `(a <=> b) == .same`
>>  if `(a ==? b) == false`, then `(a <=> b) != .same`
>>  but, if `(a ==? b) == nil`, then `a <=> b` may yield any result
>>   */
>> }
>>
>>
>> On Sat, Jul 23, 2016 at 2:35 PM, Pyry Jahkola 
>> wrote:
>>
>>> Given all this, I propose a simpler model that makes `a <=> b` follow
>>> the expected behaviour of < and ==, with the tradeoff that `a <=> .nan` and
>>> `.nan <=> b` will abort with a precondition failure:
>>>
>>> 1) We keep the current Interface of Equatable  unchanged, with !=
>>> defined in terms of ==.
>>>
>>> 2) Comparable would still refine Equatable, and include all the
>>> comparison operators, adding the new <=>:
>>>
>>> protocol Comparable : Equatable {
>>>   static func <=>(lhs: Self, rhs: Self) -> Ordering
>>>   static func <(lhs: Self, rhs: Self) -> Bool
>>>   static func >(lhs: Self, rhs: Self) -> Bool
>>>   static func <=(lhs: Self, rhs: Self) -> Bool
>>>   static func >=(lhs: Self, rhs: Self) -> Bool
>>> }
>>>
>>> The comparison operators are kept in the interface so that partially
>>> ordered types such as Double can be supported in generic code. However, the
>>> documentation should recommend against defining `<` manually.
>>>
>>> 3) Default implementations for  are provided for the
>>> following operators: ==, <, >, 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-23 Thread Xiaodi Wu via swift-evolution
Sorry to overwhelm with more emails. I'd like to show some work and further
analysis for your consideration that refines the sketch I just wrote:

Two FP values a and b can be, with respect to each other:

* ordered or unordered (per IEEE, NaN compares unordered to everything,
including itself)
* identical or not identical (for these purposes, we adopt Steve's proposed
test for identity: substitutable for all operations; thus +0 is not
identical to -0, but different binary representations of the same value are
identical)
* equal or not equal (i.e. the behavior of the == operator today)

So, if a and b are, with respect to each other:

* ordered, identical, equal -- this is what happens ordinarily with two
equal, non-NaN values
* ordered, identical, not equal -- this can never happen
* ordered, not identical, equal -- only +0 and -0
* ordered, not identical, not equal -- this is what happens ordinarily with
two unequal, non-NaN values

* unordered, identical, equal -- this can never happen, but if NaNs are to
be well-behaved (for a true equivalence relation), then we will need an
equivalence relation in which NaN == NaN
* unordered, identical, not equal -- this is what always happens, but if
NaNs are to be well-behaved, then such behavior will need to change
* unordered, not identical, equal -- this can never happen
* unordered, not identical, not equal -- this is what ordinarily happens
with one NaN and one non-NaN value

Equatable can have === and my proposed ==? as part of its protocol; a
generic ==, as originally proposed, would be defined outside the protocol.
A default implementation of ==? will forward to ===, and the generic ==
will be defined as `{ return (lhs ==? rhs) ?? (lhs === rhs) }`.
For floating point, ==? will be specialized and cease to forward to === so
that +0 and -0 compare true and NaN and anything compare nil, and floating
point == will be defined notionally as `{ return (lhs ==? rhs) ?? false }`.


On Sat, Jul 23, 2016 at 3:09 PM, Xiaodi Wu  wrote:

> Throwing out some more radical ideas here. Suppose we had instead (taking
> inspiration from IEEE notation):
>
> [Pardon any errors; I'm writing freehand in Gmail]
>
> infix operator ==? { /* figure out precedence later */ }
>
> protocol Equatable {
>   static func ==? (lhs: Self, rhs: Self) -> Bool?
>   /* semantics:
>  this function returns nil if lhs and rhs are unordered with respect
> to each other
>  otherwise, evaluate by means of a legal equivalence relation */
> }
>
> func == (lhs: T, rhs: T) -> Bool {
>   return (lhs ==? rhs) ?? false
> }
>
> protocol Comparable : Equatable {
>   static func <=> (lhs: Self, rhs: Self) -> Ordering
>   /* semantics:
>  this is a total ordering; thus:
>  if `(a ==? b) == true`, then `(a <=> b) == .same`
>  if `(a ==? b) == false`, then `(a <=> b) != .same`
>  but, if `(a ==? b) == nil`, then `a <=> b` may yield any result
>   */
> }
>
>
> On Sat, Jul 23, 2016 at 2:35 PM, Pyry Jahkola  wrote:
>
>> Given all this, I propose a simpler model that makes `a <=> b` follow the
>> expected behaviour of < and ==, with the tradeoff that `a <=> .nan` and
>> `.nan <=> b` will abort with a precondition failure:
>>
>> 1) We keep the current Interface of Equatable  unchanged, with != defined
>> in terms of ==.
>>
>> 2) Comparable would still refine Equatable, and include all the
>> comparison operators, adding the new <=>:
>>
>> protocol Comparable : Equatable {
>>   static func <=>(lhs: Self, rhs: Self) -> Ordering
>>   static func <(lhs: Self, rhs: Self) -> Bool
>>   static func >(lhs: Self, rhs: Self) -> Bool
>>   static func <=(lhs: Self, rhs: Self) -> Bool
>>   static func >=(lhs: Self, rhs: Self) -> Bool
>> }
>>
>> The comparison operators are kept in the interface so that partially
>> ordered types such as Double can be supported in generic code. However, the
>> documentation should recommend against defining `<` manually.
>>
>> 3) Default implementations for  are provided for the
>> following operators: ==, <, >, <=, and >=.
>>
>> 4) User-defined types will need to define just <=> to conform to
>> Comparable. (Even == can be omitted!)
>>
>> 5) FloatingPoint types implement custom versions of ==, <, >, <=, and >=
>> using the standard IEEE 754 definition (i.e. comparisons involving NaN
>> return false). Zero is zero; `0.0 == -0.0 && !(-0.0 < 0.0)` holds.
>>
>> 6) FloatingPoint types implement <=> as:
>>
>> func <=> (lhs: T, rhs: T) -> Ordering {
>>   if lhs < rhs { return .ascending }
>>   if rhs < lhs { return .descending }
>>   precondition(lhs == rhs)
>>   return .same
>> }
>>
>> 7) Algorithms using <=> directly should mention so in their documentation
>> as a precondition that they require total order between elements. Many
>> generic algorithms can be defined in terms of == or <, and should.
>>
>> If we took the oroginally planned route that distinguished between
>> identities such 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-23 Thread Dave Abrahams via swift-evolution

on Sat Jul 23 2016, Xiaodi Wu  wrote:

> That last sentence: division is defined in Arithmetic (IIUC--I'm not in
> front of a traditional computer ATM). 

Yes.

> I would expect, for any arithmetic type T, that the following would
> return true:
>
> let a, b, c: T
> if a == b {
> return c/a == c/b
> }
>
> This would not hold for all a and b if -0 === +0.

That would be nice, wouldn't it?  But there are lots of expected
arithmetic laws that floating point won't obey.

>
>
> On Sat, Jul 23, 2016 at 13:41 Dave Abrahams  wrote:
>
>>
>> on Sat Jul 23 2016, Xiaodi Wu  wrote:
>>
>> > On Fri, Jul 22, 2016 at 11:34 PM, Stephen Canon 
>> wrote:
>> >
>> >> > The point of this design is that `===` means identity and that `.same
>> `
>> >> > also means identity.
>> >> >
>> >> > Since this is new territory I suppose we get to decide what identity
>> >> > means for floating point.  Should +0 and -0 have the same identity or
>> >> > not?  I’ll leave the answer to folks more knowledgable about numerics
>> >> > than I.
>> >>
>> >> Boy, I take my wife out for a movie and come back to 50 new messages on
>> SE.
>> >>
>> >> I need to read the entire thread more carefully, but off the top of my
>> >> head, I think that `-0 === +0` is False.  If we’re going to have an
>> >> `isSame` / `isIdentical` / whatever it's called, I would expect it to
>> imply
>> >> substitutability.  Although -0 == +0, they are not equivalent when
>> >> substituted:
>> >>
>> >> - 1/(-0) != 1/0
>> >> - Float(-0).sign != Float(+0).sign
>> >> - etc
>> >>
>> >> This probably then implies that `<=>` is not `.same` either.  I’ll read
>> >> the rest of this and respond more completely tomorrow.
>> >>
>> >
>> > Eagerly await your evaluation of the discussion. In the meantime:
>> >
>> > I think Dave's view that `===` defines identity in terms of "essential"
>> > qualities implies that two identical values can be
>> > different/non-substitutable in "inessential" qualities. For generic
>> > purposes, the sign of zero could be one such inessential quality.
>>
>> Yes, and I think our view of how people work with numbers in swift (and
>> their protocol conformances) reflect this approach.
>>
>> http://article.gmane.org/gmane.comp.lang.swift.evolution/16321
>>
>> My sense is that we want to choose the default notions of identity and
>> ordering so as to support the way people think about these numeric
>> types, inexact though it may be.  Therefore, finding 0.0 in a sequence
>> of floats should succeed when the sequence contains -0.0, and a stable
>> sort on floating point keys should preserve the relative order of all
>> elements having +0.0 and -0.0 keys.
>>
>> People that want to work with inessential qualities such as the sign of
>> zero can always pass Float.totalOrdering (or whatever) to their
>> closure-accepting algorithms.
>>
>> [In order to support the user model, we still need to fix the semantics
>> of the default identity and ordering operations so that things like
>> sorting and searching work, which is why == and < won't cut it for these
>> purposes]
>>
>> > On the other hand, the stdlib stride algorithm is going to be borked if
>> -0
>> > < +0. Of course, as we already started to do there, we could specialize
>> for
>> > floating point and then adjust accordingly. However, it seems to me that
>> > every generic algorithm that performs comparisons and can take floating
>> > point arguments would have to be specialized to account for floating
>> point
>> > -0 != +0 (`index(of:)` being the previous example). This appears to
>> defeat
>> > the aim of trying to accommodate FP at all in this revised design for
>> > Comparables.
>>
>> Yes, that would be a disaster, generically speaking.
>>
>> > The argument for `-0 === +0` is that -0 and +0 should be equivalent when
>> > substituted for every comparison operation. For FP operations, you'd
>> > continue to test (as you have to test now) `a == b && a.sign == b.sign`
>> if
>> > you cared about the sign of zero. For non-FP arithmetic operations, hmm,
>> > not sure how to square that circle.
>>
>> I followed all of this... except, what are you getting at with that last
>> sentence?
>>
>> --
>> Dave
>>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-23 Thread Pyry Jahkola via swift-evolution
Given all this, I propose a simpler model that makes `a <=> b` follow the 
expected behaviour of < and ==, with the tradeoff that `a <=> .nan` and `.nan 
<=> b` will abort with a precondition failure:

1) We keep the current Interface of Equatable  unchanged, with != defined in 
terms of ==.

2) Comparable would still refine Equatable, and include all the comparison 
operators, adding the new <=>:

protocol Comparable : Equatable {
  static func <=>(lhs: Self, rhs: Self) -> Ordering
  static func <(lhs: Self, rhs: Self) -> Bool
  static func >(lhs: Self, rhs: Self) -> Bool
  static func <=(lhs: Self, rhs: Self) -> Bool
  static func >=(lhs: Self, rhs: Self) -> Bool
}

The comparison operators are kept in the interface so that partially ordered 
types such as Double can be supported in generic code. However, the 
documentation should recommend against defining `<` manually.

3) Default implementations for  are provided for the 
following operators: ==, <, >, <=, and >=.

4) User-defined types will need to define just <=> to conform to Comparable. 
(Even == can be omitted!)

5) FloatingPoint types implement custom versions of ==, <, >, <=, and >= using 
the standard IEEE 754 definition (i.e. comparisons involving NaN return false). 
Zero is zero; `0.0 == -0.0 && !(-0.0 < 0.0)` holds.

6) FloatingPoint types implement <=> as:

func <=> (lhs: T, rhs: T) -> Ordering {
  if lhs < rhs { return .ascending }
  if rhs < lhs { return .descending }
  precondition(lhs == rhs)
  return .same
}

7) Algorithms using <=> directly should mention so in their documentation as a 
precondition that they require total order between elements. Many generic 
algorithms can be defined in terms of == or <, and should.

If we took the oroginally planned route that distinguished between identities 
such as -0.0 vs. +0.0, or between the 2⁴⁹ - 2 ≈ 5.6 × 10¹⁴ possible NaN values 
that Double has, we'd also need to consider other oddballs like the difference 
and ordering between the Strings "ä" and "a\u{308}", which are considered equal 
but produce a different Unicode representation. I think it's best to hide those 
identities behind another interface than Equatable and Comparable, and let the 
protocols serve more mundane application logic.

— Pyry

> Dave Abrahams wrote:
> 
> 
>> on Sat Jul 23 2016, Xiaodi Wu  wrote:
>> 
>> On Fri, Jul 22, 2016 at 11:34 PM, Stephen Canon  wrote:
>> 
 The point of this design is that `===` means identity and that `.same `
 also means identity.
 
 Since this is new territory I suppose we get to decide what identity
 means for floating point.  Should +0 and -0 have the same identity or
 not?  I’ll leave the answer to folks more knowledgable about numerics
 than I.
>>> 
>>> Boy, I take my wife out for a movie and come back to 50 new messages on SE.
>>> 
>>> I need to read the entire thread more carefully, but off the top of my
>>> head, I think that `-0 === +0` is False.  If we’re going to have an
>>> `isSame` / `isIdentical` / whatever it's called, I would expect it to imply
>>> substitutability.  Although -0 == +0, they are not equivalent when
>>> substituted:
>>> 
>>> - 1/(-0) != 1/0
>>> - Float(-0).sign != Float(+0).sign
>>> - etc
>>> 
>>> This probably then implies that `<=>` is not `.same` either.  I’ll read
>>> the rest of this and respond more completely tomorrow.
>> 
>> Eagerly await your evaluation of the discussion. In the meantime:
>> 
>> I think Dave's view that `===` defines identity in terms of "essential"
>> qualities implies that two identical values can be
>> different/non-substitutable in "inessential" qualities. For generic
>> purposes, the sign of zero could be one such inessential quality.
> 
> Yes, and I think our view of how people work with numbers in swift (and
> their protocol conformances) reflect this approach.  
> 
> http://article.gmane.org/gmane.comp.lang.swift.evolution/16321
> 
> My sense is that we want to choose the default notions of identity and
> ordering so as to support the way people think about these numeric
> types, inexact though it may be.  Therefore, finding 0.0 in a sequence
> of floats should succeed when the sequence contains -0.0, and a stable
> sort on floating point keys should preserve the relative order of all
> elements having +0.0 and -0.0 keys.  
> 
> People that want to work with inessential qualities such as the sign of
> zero can always pass Float.totalOrdering (or whatever) to their
> closure-accepting algorithms.
> 
> [In order to support the user model, we still need to fix the semantics
> of the default identity and ordering operations so that things like
> sorting and searching work, which is why == and < won't cut it for these
> purposes]
> 
>> On the other hand, the stdlib stride algorithm is going to be borked if -0
>> < +0. Of course, as we already started to do there, we could specialize for
>> floating point and then adjust accordingly. 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-23 Thread Xiaodi Wu via swift-evolution
That last sentence: division is defined in Arithmetic (IIUC--I'm not in
front of a traditional computer ATM). I would expect, for any arithmetic
type T, that the following would return true:

let a, b, c: T
if a == b {
return c/a == c/b
}

This would not hold for all a and b if -0 === +0.

On Sat, Jul 23, 2016 at 13:41 Dave Abrahams  wrote:

>
> on Sat Jul 23 2016, Xiaodi Wu  wrote:
>
> > On Fri, Jul 22, 2016 at 11:34 PM, Stephen Canon 
> wrote:
> >
> >> > The point of this design is that `===` means identity and that `.same
> `
> >> > also means identity.
> >> >
> >> > Since this is new territory I suppose we get to decide what identity
> >> > means for floating point.  Should +0 and -0 have the same identity or
> >> > not?  I’ll leave the answer to folks more knowledgable about numerics
> >> > than I.
> >>
> >> Boy, I take my wife out for a movie and come back to 50 new messages on
> SE.
> >>
> >> I need to read the entire thread more carefully, but off the top of my
> >> head, I think that `-0 === +0` is False.  If we’re going to have an
> >> `isSame` / `isIdentical` / whatever it's called, I would expect it to
> imply
> >> substitutability.  Although -0 == +0, they are not equivalent when
> >> substituted:
> >>
> >> - 1/(-0) != 1/0
> >> - Float(-0).sign != Float(+0).sign
> >> - etc
> >>
> >> This probably then implies that `<=>` is not `.same` either.  I’ll read
> >> the rest of this and respond more completely tomorrow.
> >>
> >
> > Eagerly await your evaluation of the discussion. In the meantime:
> >
> > I think Dave's view that `===` defines identity in terms of "essential"
> > qualities implies that two identical values can be
> > different/non-substitutable in "inessential" qualities. For generic
> > purposes, the sign of zero could be one such inessential quality.
>
> Yes, and I think our view of how people work with numbers in swift (and
> their protocol conformances) reflect this approach.
>
> http://article.gmane.org/gmane.comp.lang.swift.evolution/16321
>
> My sense is that we want to choose the default notions of identity and
> ordering so as to support the way people think about these numeric
> types, inexact though it may be.  Therefore, finding 0.0 in a sequence
> of floats should succeed when the sequence contains -0.0, and a stable
> sort on floating point keys should preserve the relative order of all
> elements having +0.0 and -0.0 keys.
>
> People that want to work with inessential qualities such as the sign of
> zero can always pass Float.totalOrdering (or whatever) to their
> closure-accepting algorithms.
>
> [In order to support the user model, we still need to fix the semantics
> of the default identity and ordering operations so that things like
> sorting and searching work, which is why == and < won't cut it for these
> purposes]
>
> > On the other hand, the stdlib stride algorithm is going to be borked if
> -0
> > < +0. Of course, as we already started to do there, we could specialize
> for
> > floating point and then adjust accordingly. However, it seems to me that
> > every generic algorithm that performs comparisons and can take floating
> > point arguments would have to be specialized to account for floating
> point
> > -0 != +0 (`index(of:)` being the previous example). This appears to
> defeat
> > the aim of trying to accommodate FP at all in this revised design for
> > Comparables.
>
> Yes, that would be a disaster, generically speaking.
>
> > The argument for `-0 === +0` is that -0 and +0 should be equivalent when
> > substituted for every comparison operation. For FP operations, you'd
> > continue to test (as you have to test now) `a == b && a.sign == b.sign`
> if
> > you cared about the sign of zero. For non-FP arithmetic operations, hmm,
> > not sure how to square that circle.
>
> I followed all of this... except, what are you getting at with that last
> sentence?
>
> --
> Dave
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-23 Thread Dave Abrahams via swift-evolution

on Fri Jul 22 2016, jaden.geller-AT-gmail.com wrote:

> What if you wanted to filter such that you keep values less than some
> element that happens to be positive zero; might that keep around any
> negative zeros? Seems problematic.

I agree.

>> On Jul 22, 2016, at 7:53 PM, Dave Abrahams  wrote:
>> 
>> 
>>> on Fri Jul 22 2016, Xiaodi Wu  wrote:
>>> 
 On Fri, Jul 22, 2016 at 9:38 PM,  wrote:
 
 This seems reasonable to me. I don't see why `===` has to do a total order
 comparison when we already have another operator, `<=>`, that does that.
>>> 
>>> I take it back. It wouldn't solve the issue that generic `<` would
>>> still behave in surprising ways, where two equal floating point values
>>> represented differently might be less than each other or greater than
>>> each other.
>> 
>> I wonder if that's really a problem.  What generic algorithm are you
>> going to run on a collection of floats where it *would* be problematic?
>> Hmm, stableSort would not necessarily preserve the order of zeros in the
>> original collection if it contained both positive and negative zeros.
>> 
>>> I think what we really want is all identity and comparison divorced
>>> from IEEE totalOrder.
>> 
>> That might work.  Thanks for thinking this problem through; keep it up!
>> 
 On Jul 22, 2016, at 7:35 PM, Xiaodi Wu  wrote:
 
 On Fri, Jul 22, 2016 at 9:28 PM, Dave Abrahams 
 wrote:
 
> 
>> on Fri Jul 22 2016, Xiaodi Wu  wrote:
>> 
>> On Fri, Jul 22, 2016 at 9:13 PM, Matthew Johnson <
> matt...@anandabits.com>
>> wrote:
>> 
>>> 
>>> On Jul 22, 2016, at 9:10 PM, Xiaodi Wu  wrote:
>>> 
>>> On Fri, Jul 22, 2016 at 9:08 PM, Matthew Johnson <
> matt...@anandabits.com>
>>> wrote:
>>> 
 
 On Jul 22, 2016, at 9:04 PM, Xiaodi Wu  wrote:
 
 On Fri, Jul 22, 2016 at 8:57 PM, Matthew Johnson <
> matt...@anandabits.com>
 wrote:
 
> 
> On Jul 22, 2016, at 8:54 PM, Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
> 
> On Fri, Jul 22, 2016 at 8:52 PM, Jaden Geller via swift-evolution <
> swift-evolution@swift.org> wrote:
> 
>> "The totalOrder predicate will order these cases, and it also
>> distinguishes between different representations of NaNs and between
> the
>> same decimal floating point number encoded in different ways."
>> - [Wikipedia](
> https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate
>> )
>> 
>> Sounds like `===` should not return `true` for zeros of different
>> signs, then.
> 
> Fair enough; the result of that will be, as Pyry noted above, that:
> 
> ```
> [-0.0, 1.0, .nan, 0.0].firstIndex(of: 0.0) //=> 3, not 0
> ```
> 
> 
> Maybe we need floating point specific implementations of some
> algorithms
> to resolve this problem?
> 
> It doesn’t seem like there is a way to provide the semantics
> required by
> generic algorithms and still provide the expected behavior for
> floating
> point values.
 
 Well, what I'm trying to say is that generic algorithms such as
 `index(of:)` require only an equivalence relation. For floating point
 types, there are three ways to slice it:
 
 1. NaN != NaN and +0 == -0 [what the traditional comparison operators
> are
 constrained to do]
 2. NaN == NaN, +0 == -0, and the same number encoded different ways
 compare equal
 3. NaN == NaN, +0 != -0, and the same number encoded different ways
 compare not equal
 
 Both #2 and #3 can fall out of valid equivalence relations; if `===`
 behaved like #2 for FloatingPoint types, then generic algorithms work
> just
 fine. If we insist on using a total ordering defined by `<=>` all the
> time,
 then we've got problems.
 
 
 And if we don’t then we’re back to 3 different concepts of equality.
 There is definitely a tradeoff no matter what we choose.
>>> 
>>> If some types have three concepts of equality, each with their
> particular
>>> use, why must we eliminate one of them?
>>> 
>>> 
>>> This isn’t about eliminating concepts of equality for a type.  They can
>>> have 42 if they want.
>>> 
>>> This is about the right way to define the semantics of specific
>>> protocols.  It says nothing about additional notions of equality a
> type may
>>> have available.
>>> 
>>> The difficulty is finding a design for the protocols that makes sense
> with
>>> floating point types 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-23 Thread Dave Abrahams via swift-evolution

on Sat Jul 23 2016, Xiaodi Wu  wrote:

> On Fri, Jul 22, 2016 at 11:34 PM, Stephen Canon  wrote:
>
>> > The point of this design is that `===` means identity and that `.same `
>> > also means identity.
>> >
>> > Since this is new territory I suppose we get to decide what identity
>> > means for floating point.  Should +0 and -0 have the same identity or
>> > not?  I’ll leave the answer to folks more knowledgable about numerics
>> > than I.
>>
>> Boy, I take my wife out for a movie and come back to 50 new messages on SE.
>>
>> I need to read the entire thread more carefully, but off the top of my
>> head, I think that `-0 === +0` is False.  If we’re going to have an
>> `isSame` / `isIdentical` / whatever it's called, I would expect it to imply
>> substitutability.  Although -0 == +0, they are not equivalent when
>> substituted:
>>
>> - 1/(-0) != 1/0
>> - Float(-0).sign != Float(+0).sign
>> - etc
>>
>> This probably then implies that `<=>` is not `.same` either.  I’ll read
>> the rest of this and respond more completely tomorrow.
>>
>
> Eagerly await your evaluation of the discussion. In the meantime:
>
> I think Dave's view that `===` defines identity in terms of "essential"
> qualities implies that two identical values can be
> different/non-substitutable in "inessential" qualities. For generic
> purposes, the sign of zero could be one such inessential quality.

Yes, and I think our view of how people work with numbers in swift (and
their protocol conformances) reflect this approach.  

http://article.gmane.org/gmane.comp.lang.swift.evolution/16321

My sense is that we want to choose the default notions of identity and
ordering so as to support the way people think about these numeric
types, inexact though it may be.  Therefore, finding 0.0 in a sequence
of floats should succeed when the sequence contains -0.0, and a stable
sort on floating point keys should preserve the relative order of all
elements having +0.0 and -0.0 keys.  

People that want to work with inessential qualities such as the sign of
zero can always pass Float.totalOrdering (or whatever) to their
closure-accepting algorithms.

[In order to support the user model, we still need to fix the semantics
of the default identity and ordering operations so that things like
sorting and searching work, which is why == and < won't cut it for these
purposes]

> On the other hand, the stdlib stride algorithm is going to be borked if -0
> < +0. Of course, as we already started to do there, we could specialize for
> floating point and then adjust accordingly. However, it seems to me that
> every generic algorithm that performs comparisons and can take floating
> point arguments would have to be specialized to account for floating point
> -0 != +0 (`index(of:)` being the previous example). This appears to defeat
> the aim of trying to accommodate FP at all in this revised design for
> Comparables.

Yes, that would be a disaster, generically speaking.

> The argument for `-0 === +0` is that -0 and +0 should be equivalent when
> substituted for every comparison operation. For FP operations, you'd
> continue to test (as you have to test now) `a == b && a.sign == b.sign` if
> you cared about the sign of zero. For non-FP arithmetic operations, hmm,
> not sure how to square that circle.

I followed all of this... except, what are you getting at with that last
sentence?

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


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-23 Thread Xiaodi Wu via swift-evolution
On Fri, Jul 22, 2016 at 11:34 PM, Stephen Canon  wrote:

> > The point of this design is that `===` means identity and that `.same `
> > also means identity.
> >
> > Since this is new territory I suppose we get to decide what identity
> > means for floating point.  Should +0 and -0 have the same identity or
> > not?  I’ll leave the answer to folks more knowledgable about numerics
> > than I.
>
> Boy, I take my wife out for a movie and come back to 50 new messages on SE.
>
> I need to read the entire thread more carefully, but off the top of my
> head, I think that `-0 === +0` is False.  If we’re going to have an
> `isSame` / `isIdentical` / whatever it's called, I would expect it to imply
> substitutability.  Although -0 == +0, they are not equivalent when
> substituted:
>
> - 1/(-0) != 1/0
> - Float(-0).sign != Float(+0).sign
> - etc
>
> This probably then implies that `<=>` is not `.same` either.  I’ll read
> the rest of this and respond more completely tomorrow.
>

Eagerly await your evaluation of the discussion. In the meantime:

I think Dave's view that `===` defines identity in terms of "essential"
qualities implies that two identical values can be
different/non-substitutable in "inessential" qualities. For generic
purposes, the sign of zero could be one such inessential quality.

On the other hand, the stdlib stride algorithm is going to be borked if -0
< +0. Of course, as we already started to do there, we could specialize for
floating point and then adjust accordingly. However, it seems to me that
every generic algorithm that performs comparisons and can take floating
point arguments would have to be specialized to account for floating point
-0 != +0 (`index(of:)` being the previous example). This appears to defeat
the aim of trying to accommodate FP at all in this revised design for
Comparables.

The argument for `-0 === +0` is that -0 and +0 should be equivalent when
substituted for every comparison operation. For FP operations, you'd
continue to test (as you have to test now) `a == b && a.sign == b.sign` if
you cared about the sign of zero. For non-FP arithmetic operations, hmm,
not sure how to square that circle.


> – Steve
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-23 Thread Johannes Neubauer via swift-evolution

> Am 23.07.2016 um 06:34 schrieb Stephen Canon via swift-evolution 
> :
> 
>> The point of this design is that `===` means identity and that `.same `
>> also means identity.
>> 
>> Since this is new territory I suppose we get to decide what identity
>> means for floating point.  Should +0 and -0 have the same identity or
>> not?  I’ll leave the answer to folks more knowledgable about numerics
>> than I.
> 
> Boy, I take my wife out for a movie and come back to 50 new messages on SE.

I had the same feeling (short nap for the night and 96 new messages to this 
thread). I really do like the discussion whether NaN != NaN and similar cases 
are breaking the contract of ==. I think it is. I started some proposals last 
week [0], where I pointed out, that implementing equivalence relations is 
error-prone and the std lib is relying on it. We had there these special cases 
for Floating points, too. I think it is crucial to get `==` right, and then we 
get `<=` right :).

IMO, the core of the proposals idea is a good one: separating custom 
implementations from the ones that std lib relies on. Then you could have 
unchangeable default behavior (in terms of not allowing false-negatives like 
NaN != NaN) and still have custom implementations. The std lib (and any other 
library that needs equality and comparable follow the contract) will just 
continue working.

I didn’t read everything in this thread, but there were proposals to use === 
instead of isSame, but currently when I write `-0.0 === 0.0` just says that 
this operator is not implemented for Float (a value type). This makes totally 
sense, because value types have by definition no identity.

The discussions about is NaN != NaN and will code be portable and the like are 
reasonable, but Swift should IMO not try to make it easy for programmers of 
other languages to convert (hey Swift drops i++ and ++i and the like because 
this is not the focus), but to make it simple „as is“ (so for new programmers 
and for all who are willing to get oneself into Swift).

So putting all this special semantics for floating point into a special custom 
implementation would be good with me. It would be great if operators in Swift 
could contain letters. Then we could have `==` (standard conform) and `==f` or 
something like this for floating point semantics.

All the best
Johannes

[0]: 
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160718/024599.html

> 
> I need to read the entire thread more carefully, but off the top of my head, 
> I think that `-0 === +0` is False.  If we’re going to have an `isSame` / 
> `isIdentical` / whatever it's called, I would expect it to imply 
> substitutability.  Although -0 == +0, they are not equivalent when 
> substituted:
> 
> - 1/(-0) != 1/0
> - Float(-0).sign != Float(+0).sign
> - etc
> 
> This probably then implies that `<=>` is not `.same` either.  I’ll read the 
> rest of this and respond more completely tomorrow.
> 
> – Steve
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution



signature.asc
Description: Message signed with OpenPGP using GPGMail
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-23 Thread Jaden Geller via swift-evolution
What if you wanted to filter such that you keep values less than some element 
that happens to be positive zero; might that keep around any negative zeros? 
Seems problematic.

> On Jul 22, 2016, at 7:53 PM, Dave Abrahams  wrote:
> 
> 
>> on Fri Jul 22 2016, Xiaodi Wu  wrote:
>> 
>>> On Fri, Jul 22, 2016 at 9:38 PM,  wrote:
>>> 
>>> This seems reasonable to me. I don't see why `===` has to do a total order
>>> comparison when we already have another operator, `<=>`, that does that.
>> 
>> I take it back. It wouldn't solve the issue that generic `<` would
>> still behave in surprising ways, where two equal floating point values
>> represented differently might be less than each other or greater than
>> each other.
> 
> I wonder if that's really a problem.  What generic algorithm are you
> going to run on a collection of floats where it *would* be problematic?
> Hmm, stableSort would not necessarily preserve the order of zeros in the
> original collection if it contained both positive and negative zeros.
> 
>> I think what we really want is all identity and comparison divorced
>> from IEEE totalOrder.
> 
> That might work.  Thanks for thinking this problem through; keep it up!
> 
>>> On Jul 22, 2016, at 7:35 PM, Xiaodi Wu  wrote:
>>> 
>>> On Fri, Jul 22, 2016 at 9:28 PM, Dave Abrahams 
>>> wrote:
>>> 
 
> on Fri Jul 22 2016, Xiaodi Wu  wrote:
> 
> On Fri, Jul 22, 2016 at 9:13 PM, Matthew Johnson <
 matt...@anandabits.com>
> wrote:
> 
>> 
>> On Jul 22, 2016, at 9:10 PM, Xiaodi Wu  wrote:
>> 
>> On Fri, Jul 22, 2016 at 9:08 PM, Matthew Johnson <
 matt...@anandabits.com>
>> wrote:
>> 
>>> 
>>> On Jul 22, 2016, at 9:04 PM, Xiaodi Wu  wrote:
>>> 
>>> On Fri, Jul 22, 2016 at 8:57 PM, Matthew Johnson <
 matt...@anandabits.com>
>>> wrote:
>>> 
 
 On Jul 22, 2016, at 8:54 PM, Xiaodi Wu via swift-evolution <
 swift-evolution@swift.org> wrote:
 
 On Fri, Jul 22, 2016 at 8:52 PM, Jaden Geller via swift-evolution <
 swift-evolution@swift.org> wrote:
 
> "The totalOrder predicate will order these cases, and it also
> distinguishes between different representations of NaNs and between
 the
> same decimal floating point number encoded in different ways."
> - [Wikipedia](
 https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate
> )
> 
> Sounds like `===` should not return `true` for zeros of different
> signs, then.
 
 Fair enough; the result of that will be, as Pyry noted above, that:
 
 ```
 [-0.0, 1.0, .nan, 0.0].firstIndex(of: 0.0) //=> 3, not 0
 ```
 
 
 Maybe we need floating point specific implementations of some
 algorithms
 to resolve this problem?
 
 It doesn’t seem like there is a way to provide the semantics
 required by
 generic algorithms and still provide the expected behavior for
 floating
 point values.
>>> 
>>> Well, what I'm trying to say is that generic algorithms such as
>>> `index(of:)` require only an equivalence relation. For floating point
>>> types, there are three ways to slice it:
>>> 
>>> 1. NaN != NaN and +0 == -0 [what the traditional comparison operators
 are
>>> constrained to do]
>>> 2. NaN == NaN, +0 == -0, and the same number encoded different ways
>>> compare equal
>>> 3. NaN == NaN, +0 != -0, and the same number encoded different ways
>>> compare not equal
>>> 
>>> Both #2 and #3 can fall out of valid equivalence relations; if `===`
>>> behaved like #2 for FloatingPoint types, then generic algorithms work
 just
>>> fine. If we insist on using a total ordering defined by `<=>` all the
 time,
>>> then we've got problems.
>>> 
>>> 
>>> And if we don’t then we’re back to 3 different concepts of equality.
>>> There is definitely a tradeoff no matter what we choose.
>> 
>> If some types have three concepts of equality, each with their
 particular
>> use, why must we eliminate one of them?
>> 
>> 
>> This isn’t about eliminating concepts of equality for a type.  They can
>> have 42 if they want.
>> 
>> This is about the right way to define the semantics of specific
>> protocols.  It says nothing about additional notions of equality a
 type may
>> have available.
>> 
>> The difficulty is finding a design for the protocols that makes sense
 with
>> floating point types because we want them to be able to conform to the
>> protocols.
> 
> Agreed. My argument is that if a Comparable can define its own `===`,
 still
> supplying a valid equivalence 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Stephen Canon via swift-evolution
> The point of this design is that `===` means identity and that `.same `
> also means identity.
> 
> Since this is new territory I suppose we get to decide what identity
> means for floating point.  Should +0 and -0 have the same identity or
> not?  I’ll leave the answer to folks more knowledgable about numerics
> than I.

Boy, I take my wife out for a movie and come back to 50 new messages on SE.

I need to read the entire thread more carefully, but off the top of my head, I 
think that `-0 === +0` is False.  If we’re going to have an `isSame` / 
`isIdentical` / whatever it's called, I would expect it to imply 
substitutability.  Although -0 == +0, they are not equivalent when substituted:

- 1/(-0) != 1/0
- Float(-0).sign != Float(+0).sign
- etc

This probably then implies that `<=>` is not `.same` either.  I’ll read the 
rest of this and respond more completely tomorrow.

– Steve
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Dave Abrahams via swift-evolution

on Fri Jul 22 2016, Xiaodi Wu  wrote:

> On Fri, Jul 22, 2016 at 10:04 PM, Matthew Johnson 
> wrote:
>
>>
>> On Jul 22, 2016, at 9:57 PM, Dave Abrahams  wrote:
>>
>>
>> on Fri Jul 22 2016, Xiaodi Wu > > wrote:
>>
>> On Fri, Jul 22, 2016 at 9:46 PM, Dave Abrahams 
>> wrote:
>>
>>
>> on Fri Jul 22 2016, Xiaodi Wu > > wrote:
>>
>> On Fri, Jul 22, 2016 at 9:23 PM, Matthew Johnson >
>> wrote:
>>
>>
>> On Jul 22, 2016, at 9:17 PM, Xiaodi Wu  wrote:
>>
>> On Fri, Jul 22, 2016 at 9:15 PM, Matthew Johnson via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>
>> On Jul 22, 2016, at 9:04 PM, Dave Abrahams via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>
>> on Fri Jul 22 2016, Matthew Johnson  wrote:
>>
>> On Jul 22, 2016, at 8:37 PM, Xiaodi Wu via swift-evolution
>>  wrote:
>>
>> On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution
>> >
>>
>>  <
>> swift-evolution@swift.org>>>
>> wrote:
>>
>> on Fri Jul 22 2016, Daniel Duan > 
>> > wrote:
>>
>> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution
>> >  <
>> swift-evolution@swift.org>>>
>> wrote:
>>
>>
>> on Fri Jul 22 2016, Daniel Duan
>> >  <
>> swift-evolution@swift.org>>
>>  <
>> swift-evolution@swift.org>
>>  <
>> swift-evolution@swift.org
>> wrote:
>>
>>
>> On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
>> >  <
>> swift-evolution@swift.org>>
>>  <
>> swift-evolution@swift.org>
>>  <
>> swift-evolution@swift.org
>> wrote:
>>
>>
>> on Thu Jul 21 2016, Duan
>>
>>
>> >  <
>> swift-evolution@swift.org>>
>>  <
>> swift-evolution@swift.org>
>>  <
>> swift-evolution@swift.org>>>
>>  <
>> swift-evolution@swift.org>
>>  <
>> swift-evolution@swift.org>>
>>  <
>> swift-evolution@swift.org>
>>  <
>> swift-evolution@swift.org>
>> wrote:
>>
>> Great proposal. I want to second that areSame may mislead user to
>> think this is about identity.
>>
>> I like areEquivalent() but there may be better names.
>>
>>
>> It really *is* about identity as I posted in a previous message.  But
>> that doesn't change the fact that areEquivalent might be a better name.
>> It's one of the things we considered; it just seemed long for no real
>> benefit.
>>
>>
>> If the addresses of the arguments aren’t being used, then we don’t
>> consider
>> them part of their *identity*. I can follow this logic. My fear is most
>> users
>> won’t make this leap on their own and get the same initial impression
>>
>> as
>>
>> I did.
>> It's entirely possible this fear is unfounded. Some educated
>>
>> bikesheding
>>
>> wouldn't hurt here IMO :)
>>
>>
>> Well, it's still a very real question whether we ought to have the
>> additional API surface implied by areSame, or wether we should collapse
>> it with ===.
>>
>>
>> To spell this out (because I had to think about it for a second): ===
>> will be derived from
>> <=>,
>> but also becomes default implementation for ==, which remains open for
>> customization.
>>
>>
>> I was imagining roughly this (untested):
>>
>> /// Two references are identical if they refer to the same
>> /// instance.
>> ///
>> /// - Note: Classes with a more-refined notion of “identical”
>> ///   should conform to `Identifiable` and implement `===`.
>> func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {
>>   ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
>> }
>>
>> /// Supports testing that two values of `Self` are identical
>> ///
>> /// If `a` and `b` are of type `Self`, `a === b` means that
>> /// `a` and `b` are interchangeable in most code.  A conforming
>> /// type can document that specific observable characteristics
>> /// (such as the `capacity` of an `Array`) are inessential and
>> /// thus 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Xiaodi Wu via swift-evolution
On Fri, Jul 22, 2016 at 10:04 PM, Matthew Johnson 
wrote:

>
> On Jul 22, 2016, at 9:57 PM, Dave Abrahams  wrote:
>
>
> on Fri Jul 22 2016, Xiaodi Wu  > wrote:
>
> On Fri, Jul 22, 2016 at 9:46 PM, Dave Abrahams 
> wrote:
>
>
> on Fri Jul 22 2016, Xiaodi Wu  > wrote:
>
> On Fri, Jul 22, 2016 at 9:23 PM, Matthew Johnson 
> wrote:
>
>
> On Jul 22, 2016, at 9:17 PM, Xiaodi Wu  wrote:
>
> On Fri, Jul 22, 2016 at 9:15 PM, Matthew Johnson via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>
> On Jul 22, 2016, at 9:04 PM, Dave Abrahams via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>
> on Fri Jul 22 2016, Matthew Johnson  wrote:
>
> On Jul 22, 2016, at 8:37 PM, Xiaodi Wu via swift-evolution
>  wrote:
>
> On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution
> 
>
>  <
> swift-evolution@swift.org>>>
> wrote:
>
> on Fri Jul 22 2016, Daniel Duan  
> > wrote:
>
> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution
>   <
> swift-evolution@swift.org>>>
> wrote:
>
>
> on Fri Jul 22 2016, Daniel Duan
>   <
> swift-evolution@swift.org>>
>  <
> swift-evolution@swift.org>
>  <
> swift-evolution@swift.org
> wrote:
>
>
> On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
>   <
> swift-evolution@swift.org>>
>  <
> swift-evolution@swift.org>
>  <
> swift-evolution@swift.org
> wrote:
>
>
> on Thu Jul 21 2016, Duan
>
>
>   <
> swift-evolution@swift.org>>
>  <
> swift-evolution@swift.org>
>  <
> swift-evolution@swift.org>>>
>  <
> swift-evolution@swift.org>
>  <
> swift-evolution@swift.org>>
>  <
> swift-evolution@swift.org>
>  <
> swift-evolution@swift.org>
> wrote:
>
> Great proposal. I want to second that areSame may mislead user to
> think this is about identity.
>
> I like areEquivalent() but there may be better names.
>
>
> It really *is* about identity as I posted in a previous message.  But
> that doesn't change the fact that areEquivalent might be a better name.
> It's one of the things we considered; it just seemed long for no real
> benefit.
>
>
> If the addresses of the arguments aren’t being used, then we don’t
> consider
> them part of their *identity*. I can follow this logic. My fear is most
> users
> won’t make this leap on their own and get the same initial impression
>
> as
>
> I did.
> It's entirely possible this fear is unfounded. Some educated
>
> bikesheding
>
> wouldn't hurt here IMO :)
>
>
> Well, it's still a very real question whether we ought to have the
> additional API surface implied by areSame, or wether we should collapse
> it with ===.
>
>
> To spell this out (because I had to think about it for a second): ===
> will be derived from
> <=>,
> but also becomes default implementation for ==, which remains open for
> customization.
>
>
> I was imagining roughly this (untested):
>
> /// Two references are identical if they refer to the same
> /// instance.
> ///
> /// - Note: Classes with a more-refined notion of “identical”
> ///   should conform to `Identifiable` and implement `===`.
> func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {
>   ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
> }
>
> /// Supports testing that two values of `Self` are identical
> ///
> /// If `a` and `b` are of type `Self`, `a === b` means that
> /// `a` and `b` are interchangeable in most code.  A conforming
> /// type can document that specific observable characteristics
> /// (such as the `capacity` of an `Array`) are inessential and
> /// thus not to be considered as part of the interchangeability
> /// guarantee.
> ///
> /// - Requires: `===` induces an equivalence relation over
> ///   instances.
> /// - Note: conforming types will gain 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Xiaodi Wu via swift-evolution
On Fri, Jul 22, 2016 at 9:57 PM, Dave Abrahams  wrote:

>
> on Fri Jul 22 2016, Xiaodi Wu  wrote:
>
> > On Fri, Jul 22, 2016 at 9:46 PM, Dave Abrahams 
> wrote:
> >
> >>
> >> on Fri Jul 22 2016, Xiaodi Wu  wrote:
> >>
> >> > On Fri, Jul 22, 2016 at 9:23 PM, Matthew Johnson <
> matt...@anandabits.com
> >> >
> >> > wrote:
> >> >
> >> >>
> >> >> On Jul 22, 2016, at 9:17 PM, Xiaodi Wu  wrote:
> >> >>
> >> >> On Fri, Jul 22, 2016 at 9:15 PM, Matthew Johnson via swift-evolution
> <
> >> >> swift-evolution@swift.org> wrote:
> >> >>
> >> >>>
> >> >>> On Jul 22, 2016, at 9:04 PM, Dave Abrahams via swift-evolution <
> >> >>> swift-evolution@swift.org> wrote:
> >> >>>
> >> >>>
> >> >>> on Fri Jul 22 2016, Matthew Johnson 
> wrote:
> >> >>>
> >> >>> On Jul 22, 2016, at 8:37 PM, Xiaodi Wu via swift-evolution
> >> >>>  wrote:
> >> >>>
> >> >>> On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution
> >> >>>  >> >>>
> >> >>>
> >> >>> >>
> >> >>> wrote:
> >> >>>
> >> >>> on Fri Jul 22 2016, Daniel Duan  >> >>> > wrote:
> >> >>>
> >> >>> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution
> >> >>>  >> >>> >>
> >> >>> wrote:
> >> >>>
> >> >>>
> >> >>> on Fri Jul 22 2016, Daniel Duan
> >> >>>  >> >>> >
> >> >>> 
> >> >>>  >> >>> wrote:
> >> >>>
> >> >>>
> >> >>> On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
> >> >>>  >> >>> >
> >> >>> 
> >> >>>  >> >>> wrote:
> >> >>>
> >> >>>
> >> >>> on Thu Jul 21 2016, Duan
> >> >>>
> >> >>>
> >> >>>  >> >>> >
> >> >>> 
> >> >>> >>
> >> >>> 
> >> >>> >
> >> >>> 
> >> >>> 
> >> >>> wrote:
> >> >>>
> >> >>> Great proposal. I want to second that areSame may mislead user to
> >> >>> think this is about identity.
> >> >>>
> >> >>> I like areEquivalent() but there may be better names.
> >> >>>
> >> >>>
> >> >>> It really *is* about identity as I posted in a previous message.
> But
> >> >>> that doesn't change the fact that areEquivalent might be a better
> name.
> >> >>> It's one of the things we considered; it just seemed long for no
> real
> >> >>> benefit.
> >> >>>
> >> >>>
> >> >>> If the addresses of the arguments aren’t being used, then we don’t
> >> >>> consider
> >> >>> them part of their *identity*. I can follow this logic. My fear is
> most
> >> >>> users
> >> >>> won’t make this leap on their own and get the same initial
> impression
> >> as
> >> >>> I did.
> >> >>> It's entirely possible this fear is unfounded. Some educated
> >> bikesheding
> >> >>> wouldn't hurt here IMO :)
> >> >>>
> >> >>>
> >> >>> Well, it's still a very real question whether we ought to have the
> >> >>> additional API surface implied by areSame, or wether we should
> collapse
> >> >>> it with ===.
> >> >>>
> >> >>>
> >> >>> To spell this out (because I had to think about it for a second):
> ===
> >> >>> will be derived from
> >> >>> <=>,
> >> >>> but also becomes default implementation for ==, which remains open
> for
> >> >>> customization.
> >> >>>
> >> >>>
> >> >>> I was imagining roughly this (untested):
> >> >>>
> >> >>>  /// Two references are identical if they refer to the same
> >> >>>  /// instance.
> >> >>>  ///
> >> >>>  /// - Note: Classes with a more-refined notion of “identical”
> >> >>>  ///   should conform to `Identifiable` and implement `===`.
> >> >>>  func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {
> >> >>>ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
> >> >>>  }
> >> >>>
> >> >>>  /// Supports testing that two values of `Self` are identical
> >> >>>  ///
> >> >>>  /// If `a` and `b` are of type `Self`, `a === b` means that
> >> >>>  /// `a` and `b` are interchangeable in most code.  A conforming
> >> >>>  /// type can document that specific observable characteristics
> >> >>>  /// (such as the `capacity` of an `Array`) are inessential and
> >> >>>  

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Matthew Johnson via swift-evolution

> On Jul 22, 2016, at 9:57 PM, Dave Abrahams  wrote:
> 
> 
> on Fri Jul 22 2016, Xiaodi Wu  > wrote:
> 
>> On Fri, Jul 22, 2016 at 9:46 PM, Dave Abrahams  wrote:
>> 
>>> 
>>> on Fri Jul 22 2016, Xiaodi Wu  wrote:
>>> 
 On Fri, Jul 22, 2016 at 9:23 PM, Matthew Johnson  
> On Jul 22, 2016, at 9:17 PM, Xiaodi Wu  wrote:
> 
> On Fri, Jul 22, 2016 at 9:15 PM, Matthew Johnson via swift-evolution <
> swift-evolution@swift.org> wrote:
> 
>> 
>> On Jul 22, 2016, at 9:04 PM, Dave Abrahams via swift-evolution <
>> swift-evolution@swift.org> wrote:
>> 
>> 
>> on Fri Jul 22 2016, Matthew Johnson  wrote:
>> 
>> On Jul 22, 2016, at 8:37 PM, Xiaodi Wu via swift-evolution
>>  wrote:
>> 
>> On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution
>> > 
>> 
>> >>
>> wrote:
>> 
>> on Fri Jul 22 2016, Daniel Duan > > wrote:
>> 
>> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution
>> > >>
>> wrote:
>> 
>> 
>> on Fri Jul 22 2016, Daniel Duan
>> > >
>> 
>> > wrote:
>> 
>> 
>> On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
>> > >
>> 
>> > wrote:
>> 
>> 
>> on Thu Jul 21 2016, Duan
>> 
>> 
>> > >
>> 
>> >>
>> 
>> >
>> 
>> 
>> wrote:
>> 
>> Great proposal. I want to second that areSame may mislead user to
>> think this is about identity.
>> 
>> I like areEquivalent() but there may be better names.
>> 
>> 
>> It really *is* about identity as I posted in a previous message.  But
>> that doesn't change the fact that areEquivalent might be a better name.
>> It's one of the things we considered; it just seemed long for no real
>> benefit.
>> 
>> 
>> If the addresses of the arguments aren’t being used, then we don’t
>> consider
>> them part of their *identity*. I can follow this logic. My fear is most
>> users
>> won’t make this leap on their own and get the same initial impression
>>> as
>> I did.
>> It's entirely possible this fear is unfounded. Some educated
>>> bikesheding
>> wouldn't hurt here IMO :)
>> 
>> 
>> Well, it's still a very real question whether we ought to have the
>> additional API surface implied by areSame, or wether we should collapse
>> it with ===.
>> 
>> 
>> To spell this out (because I had to think about it for a second): ===
>> will be derived from
>> <=>,
>> but also becomes default implementation for ==, which remains open for
>> customization.
>> 
>> 
>> I was imagining roughly this (untested):
>> 
>> /// Two references are identical if they refer to the same
>> /// instance.
>> ///
>> /// - Note: Classes with a more-refined notion of “identical”
>> ///   should conform to `Identifiable` and implement `===`.
>> func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {
>>   ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
>> }
>> 
>> /// Supports testing that two values of `Self` are identical
>> ///
>> /// If `a` and `b` are of type `Self`, `a === b` means that
>> /// `a` and `b` are interchangeable in most code.  A conforming
>> /// type can document that specific observable characteristics
>> /// (such as the `capacity` of an `Array`) are inessential and
>> /// thus not to be considered as part of the interchangeability
>> /// guarantee.
>> ///
>> /// - Requires: `===` induces an equivalence relation over
>> ///   instances.
>> /// - Note: 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Dave Abrahams via swift-evolution

on Fri Jul 22 2016, Xiaodi Wu  wrote:

> On Fri, Jul 22, 2016 at 9:46 PM, Dave Abrahams  wrote:
>
>>
>> on Fri Jul 22 2016, Xiaodi Wu  wrote:
>>
>> > On Fri, Jul 22, 2016 at 9:23 PM, Matthew Johnson > >
>> > wrote:
>> >
>> >>
>> >> On Jul 22, 2016, at 9:17 PM, Xiaodi Wu  wrote:
>> >>
>> >> On Fri, Jul 22, 2016 at 9:15 PM, Matthew Johnson via swift-evolution <
>> >> swift-evolution@swift.org> wrote:
>> >>
>> >>>
>> >>> On Jul 22, 2016, at 9:04 PM, Dave Abrahams via swift-evolution <
>> >>> swift-evolution@swift.org> wrote:
>> >>>
>> >>>
>> >>> on Fri Jul 22 2016, Matthew Johnson  wrote:
>> >>>
>> >>> On Jul 22, 2016, at 8:37 PM, Xiaodi Wu via swift-evolution
>> >>>  wrote:
>> >>>
>> >>> On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution
>> >>> > >>>
>> >>>
>> >>> >>
>> >>> wrote:
>> >>>
>> >>> on Fri Jul 22 2016, Daniel Duan > >>> > wrote:
>> >>>
>> >>> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution
>> >>> > >>> >>
>> >>> wrote:
>> >>>
>> >>>
>> >>> on Fri Jul 22 2016, Daniel Duan
>> >>> > >>> >
>> >>> 
>> >>> > >>> wrote:
>> >>>
>> >>>
>> >>> On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
>> >>> > >>> >
>> >>> 
>> >>> > >>> wrote:
>> >>>
>> >>>
>> >>> on Thu Jul 21 2016, Duan
>> >>>
>> >>>
>> >>> > >>> >
>> >>> 
>> >>> >>
>> >>> 
>> >>> >
>> >>> 
>> >>> 
>> >>> wrote:
>> >>>
>> >>> Great proposal. I want to second that areSame may mislead user to
>> >>> think this is about identity.
>> >>>
>> >>> I like areEquivalent() but there may be better names.
>> >>>
>> >>>
>> >>> It really *is* about identity as I posted in a previous message.  But
>> >>> that doesn't change the fact that areEquivalent might be a better name.
>> >>> It's one of the things we considered; it just seemed long for no real
>> >>> benefit.
>> >>>
>> >>>
>> >>> If the addresses of the arguments aren’t being used, then we don’t
>> >>> consider
>> >>> them part of their *identity*. I can follow this logic. My fear is most
>> >>> users
>> >>> won’t make this leap on their own and get the same initial impression
>> as
>> >>> I did.
>> >>> It's entirely possible this fear is unfounded. Some educated
>> bikesheding
>> >>> wouldn't hurt here IMO :)
>> >>>
>> >>>
>> >>> Well, it's still a very real question whether we ought to have the
>> >>> additional API surface implied by areSame, or wether we should collapse
>> >>> it with ===.
>> >>>
>> >>>
>> >>> To spell this out (because I had to think about it for a second): ===
>> >>> will be derived from
>> >>> <=>,
>> >>> but also becomes default implementation for ==, which remains open for
>> >>> customization.
>> >>>
>> >>>
>> >>> I was imagining roughly this (untested):
>> >>>
>> >>>  /// Two references are identical if they refer to the same
>> >>>  /// instance.
>> >>>  ///
>> >>>  /// - Note: Classes with a more-refined notion of “identical”
>> >>>  ///   should conform to `Identifiable` and implement `===`.
>> >>>  func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {
>> >>>ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
>> >>>  }
>> >>>
>> >>>  /// Supports testing that two values of `Self` are identical
>> >>>  ///
>> >>>  /// If `a` and `b` are of type `Self`, `a === b` means that
>> >>>  /// `a` and `b` are interchangeable in most code.  A conforming
>> >>>  /// type can document that specific observable characteristics
>> >>>  /// (such as the `capacity` of an `Array`) are inessential and
>> >>>  /// thus not to be considered as part of the interchangeability
>> >>>  /// guarantee.
>> >>>  ///
>> >>>  /// - Requires: `===` induces an equivalence relation over
>> >>>  ///   instances.
>> >>>  /// - Note: conforming types will gain an `==` operator that
>> >>>  ///   forwards to `===`.
>> >>>  /// - Note: Types that require domain-specific `==`

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Xiaodi Wu via swift-evolution
On Fri, Jul 22, 2016 at 9:53 PM, Dave Abrahams  wrote:

>
> on Fri Jul 22 2016, Xiaodi Wu  wrote:
>
> > On Fri, Jul 22, 2016 at 9:38 PM,  wrote:
> >
> >> This seems reasonable to me. I don't see why `===` has to do a total
> order
> >> comparison when we already have another operator, `<=>`, that does that.
> >>
> >
> > I take it back. It wouldn't solve the issue that generic `<` would
> > still behave in surprising ways, where two equal floating point values
> > represented differently might be less than each other or greater than
> > each other.
>
> I wonder if that's really a problem.  What generic algorithm are you
> going to run on a collection of floats where it *would* be problematic?
>

I don't think they exist currently in stdlib, but any algorithm where
you're taking a subsequence prefix from a sorted collection up to a given
value might return a chunk of values that equal the value but compare
less-than ("ascending").


> Hmm, stableSort would not necessarily preserve the order of zeros in the
> original collection if it contained both positive and negative zeros.
>
> > I think what we really want is all identity and comparison divorced
> > from IEEE totalOrder.
>
> That might work.  Thanks for thinking this problem through; keep it up!
>
> >> On Jul 22, 2016, at 7:35 PM, Xiaodi Wu  wrote:
> >>
> >> On Fri, Jul 22, 2016 at 9:28 PM, Dave Abrahams 
> >> wrote:
> >>
> >>>
> >>> on Fri Jul 22 2016, Xiaodi Wu  wrote:
> >>>
> >>> > On Fri, Jul 22, 2016 at 9:13 PM, Matthew Johnson <
> >>> matt...@anandabits.com>
> >>> > wrote:
> >>> >
> >>> >>
> >>> >> On Jul 22, 2016, at 9:10 PM, Xiaodi Wu  wrote:
> >>> >>
> >>> >> On Fri, Jul 22, 2016 at 9:08 PM, Matthew Johnson <
> >>> matt...@anandabits.com>
> >>> >> wrote:
> >>> >>
> >>> >>>
> >>> >>> On Jul 22, 2016, at 9:04 PM, Xiaodi Wu 
> wrote:
> >>> >>>
> >>> >>> On Fri, Jul 22, 2016 at 8:57 PM, Matthew Johnson <
> >>> matt...@anandabits.com>
> >>> >>>  wrote:
> >>> >>>
> >>> 
> >>>  On Jul 22, 2016, at 8:54 PM, Xiaodi Wu via swift-evolution <
> >>>  swift-evolution@swift.org> wrote:
> >>> 
> >>>  On Fri, Jul 22, 2016 at 8:52 PM, Jaden Geller via swift-evolution
> <
> >>>  swift-evolution@swift.org> wrote:
> >>> 
> >>> > "The totalOrder predicate will order these cases, and it also
> >>> > distinguishes between different representations of NaNs and
> between
> >>> the
> >>> > same decimal floating point number encoded in different ways."
> >>> > - [Wikipedia](
> >>> >
> >>>
> https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate
> >>> > )
> >>> >
> >>> > Sounds like `===` should not return `true` for zeros of different
> >>> > signs, then.
> >>> >
> >>> 
> >>>  Fair enough; the result of that will be, as Pyry noted above,
> that:
> >>> 
> >>>  ```
> >>>  [-0.0, 1.0, .nan, 0.0].firstIndex(of: 0.0) //=> 3, not 0
> >>>  ```
> >>> 
> >>> 
> >>>  Maybe we need floating point specific implementations of some
> >>> algorithms
> >>>  to resolve this problem?
> >>> 
> >>>  It doesn’t seem like there is a way to provide the semantics
> >>> required by
> >>>  generic algorithms and still provide the expected behavior for
> >>> floating
> >>>  point values.
> >>> 
> >>> >>>
> >>> >>> Well, what I'm trying to say is that generic algorithms such as
> >>> >>> `index(of:)` require only an equivalence relation. For floating
> point
> >>> >>> types, there are three ways to slice it:
> >>> >>>
> >>> >>> 1. NaN != NaN and +0 == -0 [what the traditional comparison
> operators
> >>> are
> >>> >>> constrained to do]
> >>> >>> 2. NaN == NaN, +0 == -0, and the same number encoded different ways
> >>> >>> compare equal
> >>> >>> 3. NaN == NaN, +0 != -0, and the same number encoded different ways
> >>> >>> compare not equal
> >>> >>>
> >>> >>> Both #2 and #3 can fall out of valid equivalence relations; if
> `===`
> >>> >>> behaved like #2 for FloatingPoint types, then generic algorithms
> work
> >>> just
> >>> >>> fine. If we insist on using a total ordering defined by `<=>` all
> the
> >>> time,
> >>> >>> then we've got problems.
> >>> >>>
> >>> >>>
> >>> >>> And if we don’t then we’re back to 3 different concepts of
> equality.
> >>> >>> There is definitely a tradeoff no matter what we choose.
> >>> >>>
> >>> >>
> >>> >> If some types have three concepts of equality, each with their
> >>> particular
> >>> >> use, why must we eliminate one of them?
> >>> >>
> >>> >>
> >>> >> This isn’t about eliminating concepts of equality for a type.  They
> can
> >>> >> have 42 if they want.
> >>> >>
> >>> >> This is about the right way to define the semantics of specific
> >>> >> protocols.  It says nothing about additional notions of equality a
> >>> type may
> >>> >> have available.
> >>> >>
> >>> >> The difficulty is 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Dave Abrahams via swift-evolution

on Fri Jul 22 2016, Brent Royal-Gordon  wrote:

>> On Jul 22, 2016, at 7:23 PM, Dave Abrahams  wrote:
>> 
>> No, NSString's conformance to Identifiable (probably NSObject's,
>> actually) would define `===` in terms of `isEqual()`.  That's saying
>> identity for these types is determined by `isEqual()`.
>
> So `===` no longer tests if both instances are the same? 

In a very real sense, it does test exactly that.  It no longer tests if
there's only one instance behind the two references.

> What's the way to do that now—`ObjectIdentifier(lhs) ==
> ObjectIdentifier(rhs)`?  

That's how you test if there's really only one instance.

> (Should it still be called "Identifier" if we're taking the term
> "identifiable" for something else? 
> Do we need to change the general term "identity", as in "instances of
> reference types have an identity"?)

Good questions; we should keep them in mind as we figure out the naming.


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


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Dave Abrahams via swift-evolution

on Fri Jul 22 2016, Xiaodi Wu  wrote:

> On Fri, Jul 22, 2016 at 9:38 PM,  wrote:
>
>> This seems reasonable to me. I don't see why `===` has to do a total order
>> comparison when we already have another operator, `<=>`, that does that.
>>
>
> I take it back. It wouldn't solve the issue that generic `<` would
> still behave in surprising ways, where two equal floating point values
> represented differently might be less than each other or greater than
> each other.

I wonder if that's really a problem.  What generic algorithm are you
going to run on a collection of floats where it *would* be problematic?
Hmm, stableSort would not necessarily preserve the order of zeros in the
original collection if it contained both positive and negative zeros.

> I think what we really want is all identity and comparison divorced
> from IEEE totalOrder.

That might work.  Thanks for thinking this problem through; keep it up!

>> On Jul 22, 2016, at 7:35 PM, Xiaodi Wu  wrote:
>>
>> On Fri, Jul 22, 2016 at 9:28 PM, Dave Abrahams 
>> wrote:
>>
>>>
>>> on Fri Jul 22 2016, Xiaodi Wu  wrote:
>>>
>>> > On Fri, Jul 22, 2016 at 9:13 PM, Matthew Johnson <
>>> matt...@anandabits.com>
>>> > wrote:
>>> >
>>> >>
>>> >> On Jul 22, 2016, at 9:10 PM, Xiaodi Wu  wrote:
>>> >>
>>> >> On Fri, Jul 22, 2016 at 9:08 PM, Matthew Johnson <
>>> matt...@anandabits.com>
>>> >> wrote:
>>> >>
>>> >>>
>>> >>> On Jul 22, 2016, at 9:04 PM, Xiaodi Wu  wrote:
>>> >>>
>>> >>> On Fri, Jul 22, 2016 at 8:57 PM, Matthew Johnson <
>>> matt...@anandabits.com>
>>> >>>  wrote:
>>> >>>
>>> 
>>>  On Jul 22, 2016, at 8:54 PM, Xiaodi Wu via swift-evolution <
>>>  swift-evolution@swift.org> wrote:
>>> 
>>>  On Fri, Jul 22, 2016 at 8:52 PM, Jaden Geller via swift-evolution <
>>>  swift-evolution@swift.org> wrote:
>>> 
>>> > "The totalOrder predicate will order these cases, and it also
>>> > distinguishes between different representations of NaNs and between
>>> the
>>> > same decimal floating point number encoded in different ways."
>>> > - [Wikipedia](
>>> >
>>> https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate
>>> > )
>>> >
>>> > Sounds like `===` should not return `true` for zeros of different
>>> > signs, then.
>>> >
>>> 
>>>  Fair enough; the result of that will be, as Pyry noted above, that:
>>> 
>>>  ```
>>>  [-0.0, 1.0, .nan, 0.0].firstIndex(of: 0.0) //=> 3, not 0
>>>  ```
>>> 
>>> 
>>>  Maybe we need floating point specific implementations of some
>>> algorithms
>>>  to resolve this problem?
>>> 
>>>  It doesn’t seem like there is a way to provide the semantics
>>> required by
>>>  generic algorithms and still provide the expected behavior for
>>> floating
>>>  point values.
>>> 
>>> >>>
>>> >>> Well, what I'm trying to say is that generic algorithms such as
>>> >>> `index(of:)` require only an equivalence relation. For floating point
>>> >>> types, there are three ways to slice it:
>>> >>>
>>> >>> 1. NaN != NaN and +0 == -0 [what the traditional comparison operators
>>> are
>>> >>> constrained to do]
>>> >>> 2. NaN == NaN, +0 == -0, and the same number encoded different ways
>>> >>> compare equal
>>> >>> 3. NaN == NaN, +0 != -0, and the same number encoded different ways
>>> >>> compare not equal
>>> >>>
>>> >>> Both #2 and #3 can fall out of valid equivalence relations; if `===`
>>> >>> behaved like #2 for FloatingPoint types, then generic algorithms work
>>> just
>>> >>> fine. If we insist on using a total ordering defined by `<=>` all the
>>> time,
>>> >>> then we've got problems.
>>> >>>
>>> >>>
>>> >>> And if we don’t then we’re back to 3 different concepts of equality.
>>> >>> There is definitely a tradeoff no matter what we choose.
>>> >>>
>>> >>
>>> >> If some types have three concepts of equality, each with their
>>> particular
>>> >> use, why must we eliminate one of them?
>>> >>
>>> >>
>>> >> This isn’t about eliminating concepts of equality for a type.  They can
>>> >> have 42 if they want.
>>> >>
>>> >> This is about the right way to define the semantics of specific
>>> >> protocols.  It says nothing about additional notions of equality a
>>> type may
>>> >> have available.
>>> >>
>>> >> The difficulty is finding a design for the protocols that makes sense
>>> with
>>> >> floating point types because we want them to be able to conform to the
>>> >> protocols.
>>> >>
>>> >
>>> > Agreed. My argument is that if a Comparable can define its own `===`,
>>> still
>>> > supplying a valid equivalence relation but not being constrained by a
>>> > contract that `(a <=> b) == .same` iff `a === b`, then we are good to go
>>> > with floating point types.
>>>
>>> How would that work?  Can you spell out the implications, show how <=>
>>> and === would be implemented, and describe what it would mean for

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Xiaodi Wu via swift-evolution
On Fri, Jul 22, 2016 at 9:46 PM, Dave Abrahams  wrote:

>
> on Fri Jul 22 2016, Xiaodi Wu  wrote:
>
> > On Fri, Jul 22, 2016 at 9:23 PM, Matthew Johnson  >
> > wrote:
> >
> >>
> >> On Jul 22, 2016, at 9:17 PM, Xiaodi Wu  wrote:
> >>
> >> On Fri, Jul 22, 2016 at 9:15 PM, Matthew Johnson via swift-evolution <
> >> swift-evolution@swift.org> wrote:
> >>
> >>>
> >>> On Jul 22, 2016, at 9:04 PM, Dave Abrahams via swift-evolution <
> >>> swift-evolution@swift.org> wrote:
> >>>
> >>>
> >>> on Fri Jul 22 2016, Matthew Johnson  wrote:
> >>>
> >>> On Jul 22, 2016, at 8:37 PM, Xiaodi Wu via swift-evolution
> >>>  wrote:
> >>>
> >>> On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution
> >>>  >>>
> >>>
> >>> >>
> >>> wrote:
> >>>
> >>> on Fri Jul 22 2016, Daniel Duan  >>> > wrote:
> >>>
> >>> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution
> >>>  >>> >>
> >>> wrote:
> >>>
> >>>
> >>> on Fri Jul 22 2016, Daniel Duan
> >>>  >>> >
> >>> 
> >>>  >>> wrote:
> >>>
> >>>
> >>> On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
> >>>  >>> >
> >>> 
> >>>  >>> wrote:
> >>>
> >>>
> >>> on Thu Jul 21 2016, Duan
> >>>
> >>>
> >>>  >>> >
> >>> 
> >>> >>
> >>> 
> >>> >
> >>> 
> >>> 
> >>> wrote:
> >>>
> >>> Great proposal. I want to second that areSame may mislead user to
> >>> think this is about identity.
> >>>
> >>> I like areEquivalent() but there may be better names.
> >>>
> >>>
> >>> It really *is* about identity as I posted in a previous message.  But
> >>> that doesn't change the fact that areEquivalent might be a better name.
> >>> It's one of the things we considered; it just seemed long for no real
> >>> benefit.
> >>>
> >>>
> >>> If the addresses of the arguments aren’t being used, then we don’t
> >>> consider
> >>> them part of their *identity*. I can follow this logic. My fear is most
> >>> users
> >>> won’t make this leap on their own and get the same initial impression
> as
> >>> I did.
> >>> It's entirely possible this fear is unfounded. Some educated
> bikesheding
> >>> wouldn't hurt here IMO :)
> >>>
> >>>
> >>> Well, it's still a very real question whether we ought to have the
> >>> additional API surface implied by areSame, or wether we should collapse
> >>> it with ===.
> >>>
> >>>
> >>> To spell this out (because I had to think about it for a second): ===
> >>> will be derived from
> >>> <=>,
> >>> but also becomes default implementation for ==, which remains open for
> >>> customization.
> >>>
> >>>
> >>> I was imagining roughly this (untested):
> >>>
> >>>  /// Two references are identical if they refer to the same
> >>>  /// instance.
> >>>  ///
> >>>  /// - Note: Classes with a more-refined notion of “identical”
> >>>  ///   should conform to `Identifiable` and implement `===`.
> >>>  func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {
> >>>ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
> >>>  }
> >>>
> >>>  /// Supports testing that two values of `Self` are identical
> >>>  ///
> >>>  /// If `a` and `b` are of type `Self`, `a === b` means that
> >>>  /// `a` and `b` are interchangeable in most code.  A conforming
> >>>  /// type can document that specific observable characteristics
> >>>  /// (such as the `capacity` of an `Array`) are inessential and
> >>>  /// thus not to be considered as part of the interchangeability
> >>>  /// guarantee.
> >>>  ///
> >>>  /// - Requires: `===` induces an equivalence relation over
> >>>  ///   instances.
> >>>  /// - Note: conforming types will gain an `==` operator that
> >>>  ///   forwards to `===`.
> >>>  /// - Note: Types that require domain-specific `==`
> >>>  ///   implementations with different semantics (e.g. floating
> >>>  ///   point) should define a more-specific overload of `==`,
> >>>  ///   which will be used in 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Matthew Johnson via swift-evolution

> On Jul 22, 2016, at 9:46 PM, Dave Abrahams  wrote:
> 
> 
> on Fri Jul 22 2016, Xiaodi Wu  wrote:
> 
>> On Fri, Jul 22, 2016 at 9:23 PM, Matthew Johnson 
>> wrote:
>> 
>>> 
>>> On Jul 22, 2016, at 9:17 PM, Xiaodi Wu  wrote:
>>> 
>>> On Fri, Jul 22, 2016 at 9:15 PM, Matthew Johnson via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>> 
 
 On Jul 22, 2016, at 9:04 PM, Dave Abrahams via swift-evolution <
 swift-evolution@swift.org> wrote:
 
 
 on Fri Jul 22 2016, Matthew Johnson  wrote:
 
 On Jul 22, 2016, at 8:37 PM, Xiaodi Wu via swift-evolution
  wrote:
 
 On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution
 >>
 wrote:
 
 on Fri Jul 22 2016, Daniel Duan >>> > wrote:
 
 On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution
 >>
 wrote:
 
 
 on Fri Jul 22 2016, Daniel Duan
 >
 
 >
 
 >
 
 >>
 
 >
 
 
 wrote:
 
 Great proposal. I want to second that areSame may mislead user to
 think this is about identity.
 
 I like areEquivalent() but there may be better names.
 
 
 It really *is* about identity as I posted in a previous message.  But
 that doesn't change the fact that areEquivalent might be a better name.
 It's one of the things we considered; it just seemed long for no real
 benefit.
 
 
 If the addresses of the arguments aren’t being used, then we don’t
 consider
 them part of their *identity*. I can follow this logic. My fear is most
 users
 won’t make this leap on their own and get the same initial impression as
 I did.
 It's entirely possible this fear is unfounded. Some educated bikesheding
 wouldn't hurt here IMO :)
 
 
 Well, it's still a very real question whether we ought to have the
 additional API surface implied by areSame, or wether we should collapse
 it with ===.
 
 
 To spell this out (because I had to think about it for a second): ===
 will be derived from
 <=>,
 but also becomes default implementation for ==, which remains open for
 customization.
 
 
 I was imagining roughly this (untested):
 
 /// Two references are identical if they refer to the same
 /// instance.
 ///
 /// - Note: Classes with a more-refined notion of “identical”
 ///   should conform to `Identifiable` and implement `===`.
 func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {
   ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
 }
 
 /// Supports testing that two values of `Self` are identical
 ///
 /// If `a` and `b` are of type `Self`, `a === b` means that
 /// `a` and `b` are interchangeable in most code.  A conforming
 /// type can document that specific observable characteristics
 /// (such as the `capacity` of an `Array`) are inessential and
 /// thus not to be considered as part of the interchangeability
 /// guarantee.
 ///
 /// - Requires: `===` induces an equivalence relation over
 ///   instances.
 /// - Note: conforming types will gain an `==` operator that
 ///   forwards to `===`.
 /// - Note: Types that require domain-specific `==`
 ///   implementations with different semantics (e.g. floating
 ///   point) should define a more-specific overload of `==`,
 ///   which will be used in contexts where the static type is
 ///   known to the compiler.
 /// - Note: Generic code should usually use `==` 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Xiaodi Wu via swift-evolution
On Fri, Jul 22, 2016 at 9:38 PM,  wrote:

> This seems reasonable to me. I don't see why `===` has to do a total order
> comparison when we already have another operator, `<=>`, that does that.
>

I take it back. It wouldn't solve the issue that generic `<` would still
behave in surprising ways, where two equal floating point values
represented differently might be less than each other or greater than each
other. I think what we really want is all identity and comparison divorced
from IEEE totalOrder.


> On Jul 22, 2016, at 7:35 PM, Xiaodi Wu  wrote:
>
> On Fri, Jul 22, 2016 at 9:28 PM, Dave Abrahams 
> wrote:
>
>>
>> on Fri Jul 22 2016, Xiaodi Wu  wrote:
>>
>> > On Fri, Jul 22, 2016 at 9:13 PM, Matthew Johnson <
>> matt...@anandabits.com>
>> > wrote:
>> >
>> >>
>> >> On Jul 22, 2016, at 9:10 PM, Xiaodi Wu  wrote:
>> >>
>> >> On Fri, Jul 22, 2016 at 9:08 PM, Matthew Johnson <
>> matt...@anandabits.com>
>> >> wrote:
>> >>
>> >>>
>> >>> On Jul 22, 2016, at 9:04 PM, Xiaodi Wu  wrote:
>> >>>
>> >>> On Fri, Jul 22, 2016 at 8:57 PM, Matthew Johnson <
>> matt...@anandabits.com>
>> >>>  wrote:
>> >>>
>> 
>>  On Jul 22, 2016, at 8:54 PM, Xiaodi Wu via swift-evolution <
>>  swift-evolution@swift.org> wrote:
>> 
>>  On Fri, Jul 22, 2016 at 8:52 PM, Jaden Geller via swift-evolution <
>>  swift-evolution@swift.org> wrote:
>> 
>> > "The totalOrder predicate will order these cases, and it also
>> > distinguishes between different representations of NaNs and between
>> the
>> > same decimal floating point number encoded in different ways."
>> > - [Wikipedia](
>> >
>> https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate
>> > )
>> >
>> > Sounds like `===` should not return `true` for zeros of different
>> > signs, then.
>> >
>> 
>>  Fair enough; the result of that will be, as Pyry noted above, that:
>> 
>>  ```
>>  [-0.0, 1.0, .nan, 0.0].firstIndex(of: 0.0) //=> 3, not 0
>>  ```
>> 
>> 
>>  Maybe we need floating point specific implementations of some
>> algorithms
>>  to resolve this problem?
>> 
>>  It doesn’t seem like there is a way to provide the semantics
>> required by
>>  generic algorithms and still provide the expected behavior for
>> floating
>>  point values.
>> 
>> >>>
>> >>> Well, what I'm trying to say is that generic algorithms such as
>> >>> `index(of:)` require only an equivalence relation. For floating point
>> >>> types, there are three ways to slice it:
>> >>>
>> >>> 1. NaN != NaN and +0 == -0 [what the traditional comparison operators
>> are
>> >>> constrained to do]
>> >>> 2. NaN == NaN, +0 == -0, and the same number encoded different ways
>> >>> compare equal
>> >>> 3. NaN == NaN, +0 != -0, and the same number encoded different ways
>> >>> compare not equal
>> >>>
>> >>> Both #2 and #3 can fall out of valid equivalence relations; if `===`
>> >>> behaved like #2 for FloatingPoint types, then generic algorithms work
>> just
>> >>> fine. If we insist on using a total ordering defined by `<=>` all the
>> time,
>> >>> then we've got problems.
>> >>>
>> >>>
>> >>> And if we don’t then we’re back to 3 different concepts of equality.
>> >>> There is definitely a tradeoff no matter what we choose.
>> >>>
>> >>
>> >> If some types have three concepts of equality, each with their
>> particular
>> >> use, why must we eliminate one of them?
>> >>
>> >>
>> >> This isn’t about eliminating concepts of equality for a type.  They can
>> >> have 42 if they want.
>> >>
>> >> This is about the right way to define the semantics of specific
>> >> protocols.  It says nothing about additional notions of equality a
>> type may
>> >> have available.
>> >>
>> >> The difficulty is finding a design for the protocols that makes sense
>> with
>> >> floating point types because we want them to be able to conform to the
>> >> protocols.
>> >>
>> >
>> > Agreed. My argument is that if a Comparable can define its own `===`,
>> still
>> > supplying a valid equivalence relation but not being constrained by a
>> > contract that `(a <=> b) == .same` iff `a === b`, then we are good to go
>> > with floating point types.
>>
>> How would that work?  Can you spell out the implications, show how <=>
>> and === would be implemented, and describe what it would mean for
>> algorithms?
>>
>
> Right. I'm not married to this solution anymore, but I do think it could
> work. There would still be a relationship required between `===` and `<=>`.
> Namely:
>
> `a === b` if `(a <=> b) == .same`
>
> But for some values a and b, it is permitted that `a === b && (a <=> b) !=
> .same`. That is, two identical values may be ordered in a total ordering
> based on *inessential* qualities.
> Generic algorithms that need to produce a stable ordering of elements will
> use `<=>`. Those such as `index(of:)` will 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Dave Abrahams via swift-evolution

on Fri Jul 22 2016, Xiaodi Wu  wrote:

> On Fri, Jul 22, 2016 at 9:28 PM, Dave Abrahams  wrote:
>
>>
>> on Fri Jul 22 2016, Xiaodi Wu  wrote:
>>
>> > On Fri, Jul 22, 2016 at 9:13 PM, Matthew Johnson > >
>> > wrote:
>> >
>> >>
>> >> On Jul 22, 2016, at 9:10 PM, Xiaodi Wu  wrote:
>> >>
>> >> On Fri, Jul 22, 2016 at 9:08 PM, Matthew Johnson <
>> matt...@anandabits.com>
>> >> wrote:
>> >>
>> >>>
>> >>> On Jul 22, 2016, at 9:04 PM, Xiaodi Wu  wrote:
>> >>>
>> >>> On Fri, Jul 22, 2016 at 8:57 PM, Matthew Johnson <
>> matt...@anandabits.com>
>> >>>  wrote:
>> >>>
>> 
>>  On Jul 22, 2016, at 8:54 PM, Xiaodi Wu via swift-evolution <
>>  swift-evolution@swift.org> wrote:
>> 
>>  On Fri, Jul 22, 2016 at 8:52 PM, Jaden Geller via swift-evolution <
>>  swift-evolution@swift.org> wrote:
>> 
>> > "The totalOrder predicate will order these cases, and it also
>> > distinguishes between different representations of NaNs and between
>> the
>> > same decimal floating point number encoded in different ways."
>> > - [Wikipedia](
>> >
>> https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate
>> > )
>> >
>> > Sounds like `===` should not return `true` for zeros of different
>> > signs, then.
>> >
>> 
>>  Fair enough; the result of that will be, as Pyry noted above, that:
>> 
>>  ```
>>  [-0.0, 1.0, .nan, 0.0].firstIndex(of: 0.0) //=> 3, not 0
>>  ```
>> 
>> 
>>  Maybe we need floating point specific implementations of some
>> algorithms
>>  to resolve this problem?
>> 
>>  It doesn’t seem like there is a way to provide the semantics required
>> by
>>  generic algorithms and still provide the expected behavior for
>> floating
>>  point values.
>> 
>> >>>
>> >>> Well, what I'm trying to say is that generic algorithms such as
>> >>> `index(of:)` require only an equivalence relation. For floating point
>> >>> types, there are three ways to slice it:
>> >>>
>> >>> 1. NaN != NaN and +0 == -0 [what the traditional comparison operators
>> are
>> >>> constrained to do]
>> >>> 2. NaN == NaN, +0 == -0, and the same number encoded different ways
>> >>> compare equal
>> >>> 3. NaN == NaN, +0 != -0, and the same number encoded different ways
>> >>> compare not equal
>> >>>
>> >>> Both #2 and #3 can fall out of valid equivalence relations; if `===`
>> >>> behaved like #2 for FloatingPoint types, then generic algorithms work
>> just
>> >>> fine. If we insist on using a total ordering defined by `<=>` all the
>> time,
>> >>> then we've got problems.
>> >>>
>> >>>
>> >>> And if we don’t then we’re back to 3 different concepts of equality.
>> >>> There is definitely a tradeoff no matter what we choose.
>> >>>
>> >>
>> >> If some types have three concepts of equality, each with their
>> particular
>> >> use, why must we eliminate one of them?
>> >>
>> >>
>> >> This isn’t about eliminating concepts of equality for a type.  They can
>> >> have 42 if they want.
>> >>
>> >> This is about the right way to define the semantics of specific
>> >> protocols.  It says nothing about additional notions of equality a type
>> may
>> >> have available.
>> >>
>> >> The difficulty is finding a design for the protocols that makes sense
>> with
>> >> floating point types because we want them to be able to conform to the
>> >> protocols.
>> >>
>> >
>> > Agreed. My argument is that if a Comparable can define its own `===`,
>> still
>> > supplying a valid equivalence relation but not being constrained by a
>> > contract that `(a <=> b) == .same` iff `a === b`, then we are good to go
>> > with floating point types.
>>
>> How would that work?  Can you spell out the implications, show how <=>
>> and === would be implemented, and describe what it would mean for
>> algorithms?
>>
>
> Right. I'm not married to this solution anymore, but I do think it could
> work. There would still be a relationship required between `===` and `<=>`.
> Namely:
>
> `a === b` if `(a <=> b) == .same`
>
> But for some values a and b, it is permitted that `a === b && (a <=> b) !=
> .same`. That is, two identical values may be ordered in a total ordering
> based on *inessential* qualities.
> Generic algorithms that need to produce a stable ordering of elements will
> use `<=>`. Those such as `index(of:)` will use `===` to test for identity.
> Wouldn't that work?

It might, actually!  That's pretty interesting.

>>
>> > On Jul 22, 2016, at 6:48 PM, Dave Abrahams via swift-evolution <
>> > swift-evolution@swift.org> wrote:
>> >
>> >
>> > on Fri Jul 22 2016, Jaden Geller  wrote:
>> >
>> > For floating point, I'd hope that `a === b` if `(a <=> b) == .same`
>> > *but not iff*. This is to satisfy IEEE 754: "Comparisons shall
>> > ignore the sign of zero (so +0 = −0)".
>> >
>> >
>> > I don't see why both 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Jaden Geller via swift-evolution
This seems reasonable to me. I don't see why `===` has to do a total order 
comparison when we already have another operator, `<=>`, that does that.

> On Jul 22, 2016, at 7:35 PM, Xiaodi Wu  wrote:
> 
>> On Fri, Jul 22, 2016 at 9:28 PM, Dave Abrahams  wrote:
>> 
>> on Fri Jul 22 2016, Xiaodi Wu  wrote:
>> 
>> > On Fri, Jul 22, 2016 at 9:13 PM, Matthew Johnson 
>> > wrote:
>> >
>> >>
>> >> On Jul 22, 2016, at 9:10 PM, Xiaodi Wu  wrote:
>> >>
>> >> On Fri, Jul 22, 2016 at 9:08 PM, Matthew Johnson 
>> >> wrote:
>> >>
>> >>>
>> >>> On Jul 22, 2016, at 9:04 PM, Xiaodi Wu  wrote:
>> >>>
>> >>> On Fri, Jul 22, 2016 at 8:57 PM, Matthew Johnson 
>> >>>  wrote:
>> >>>
>> 
>>  On Jul 22, 2016, at 8:54 PM, Xiaodi Wu via swift-evolution <
>>  swift-evolution@swift.org> wrote:
>> 
>>  On Fri, Jul 22, 2016 at 8:52 PM, Jaden Geller via swift-evolution <
>>  swift-evolution@swift.org> wrote:
>> 
>> > "The totalOrder predicate will order these cases, and it also
>> > distinguishes between different representations of NaNs and between the
>> > same decimal floating point number encoded in different ways."
>> > - [Wikipedia](
>> > https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate
>> > )
>> >
>> > Sounds like `===` should not return `true` for zeros of different
>> > signs, then.
>> >
>> 
>>  Fair enough; the result of that will be, as Pyry noted above, that:
>> 
>>  ```
>>  [-0.0, 1.0, .nan, 0.0].firstIndex(of: 0.0) //=> 3, not 0
>>  ```
>> 
>> 
>>  Maybe we need floating point specific implementations of some algorithms
>>  to resolve this problem?
>> 
>>  It doesn’t seem like there is a way to provide the semantics required by
>>  generic algorithms and still provide the expected behavior for floating
>>  point values.
>> 
>> >>>
>> >>> Well, what I'm trying to say is that generic algorithms such as
>> >>> `index(of:)` require only an equivalence relation. For floating point
>> >>> types, there are three ways to slice it:
>> >>>
>> >>> 1. NaN != NaN and +0 == -0 [what the traditional comparison operators are
>> >>> constrained to do]
>> >>> 2. NaN == NaN, +0 == -0, and the same number encoded different ways
>> >>> compare equal
>> >>> 3. NaN == NaN, +0 != -0, and the same number encoded different ways
>> >>> compare not equal
>> >>>
>> >>> Both #2 and #3 can fall out of valid equivalence relations; if `===`
>> >>> behaved like #2 for FloatingPoint types, then generic algorithms work 
>> >>> just
>> >>> fine. If we insist on using a total ordering defined by `<=>` all the 
>> >>> time,
>> >>> then we've got problems.
>> >>>
>> >>>
>> >>> And if we don’t then we’re back to 3 different concepts of equality.
>> >>> There is definitely a tradeoff no matter what we choose.
>> >>>
>> >>
>> >> If some types have three concepts of equality, each with their particular
>> >> use, why must we eliminate one of them?
>> >>
>> >>
>> >> This isn’t about eliminating concepts of equality for a type.  They can
>> >> have 42 if they want.
>> >>
>> >> This is about the right way to define the semantics of specific
>> >> protocols.  It says nothing about additional notions of equality a type 
>> >> may
>> >> have available.
>> >>
>> >> The difficulty is finding a design for the protocols that makes sense with
>> >> floating point types because we want them to be able to conform to the
>> >> protocols.
>> >>
>> >
>> > Agreed. My argument is that if a Comparable can define its own `===`, still
>> > supplying a valid equivalence relation but not being constrained by a
>> > contract that `(a <=> b) == .same` iff `a === b`, then we are good to go
>> > with floating point types.
>> 
>> How would that work?  Can you spell out the implications, show how <=>
>> and === would be implemented, and describe what it would mean for
>> algorithms?
> 
> Right. I'm not married to this solution anymore, but I do think it could 
> work. There would still be a relationship required between `===` and `<=>`. 
> Namely:
> 
> `a === b` if `(a <=> b) == .same`
> 
> But for some values a and b, it is permitted that `a === b && (a <=> b) != 
> .same`. That is, two identical values may be ordered in a total ordering 
> based on *inessential* qualities.
> Generic algorithms that need to produce a stable ordering of elements will 
> use `<=>`. Those such as `index(of:)` will use `===` to test for identity. 
> Wouldn't that work?
> 
>> >
>> > On Jul 22, 2016, at 6:48 PM, Dave Abrahams via swift-evolution <
>> > swift-evolution@swift.org> wrote:
>> >
>> >
>> > on Fri Jul 22 2016, Jaden Geller  wrote:
>> >
>> > For floating point, I'd hope that `a === b` if `(a <=> b) == .same`
>> > *but not iff*. This is to satisfy 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Xiaodi Wu via swift-evolution
On Fri, Jul 22, 2016 at 9:28 PM, Dave Abrahams  wrote:

>
> on Fri Jul 22 2016, Xiaodi Wu  wrote:
>
> > On Fri, Jul 22, 2016 at 9:13 PM, Matthew Johnson  >
> > wrote:
> >
> >>
> >> On Jul 22, 2016, at 9:10 PM, Xiaodi Wu  wrote:
> >>
> >> On Fri, Jul 22, 2016 at 9:08 PM, Matthew Johnson <
> matt...@anandabits.com>
> >> wrote:
> >>
> >>>
> >>> On Jul 22, 2016, at 9:04 PM, Xiaodi Wu  wrote:
> >>>
> >>> On Fri, Jul 22, 2016 at 8:57 PM, Matthew Johnson <
> matt...@anandabits.com>
> >>>  wrote:
> >>>
> 
>  On Jul 22, 2016, at 8:54 PM, Xiaodi Wu via swift-evolution <
>  swift-evolution@swift.org> wrote:
> 
>  On Fri, Jul 22, 2016 at 8:52 PM, Jaden Geller via swift-evolution <
>  swift-evolution@swift.org> wrote:
> 
> > "The totalOrder predicate will order these cases, and it also
> > distinguishes between different representations of NaNs and between
> the
> > same decimal floating point number encoded in different ways."
> > - [Wikipedia](
> >
> https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate
> > )
> >
> > Sounds like `===` should not return `true` for zeros of different
> > signs, then.
> >
> 
>  Fair enough; the result of that will be, as Pyry noted above, that:
> 
>  ```
>  [-0.0, 1.0, .nan, 0.0].firstIndex(of: 0.0) //=> 3, not 0
>  ```
> 
> 
>  Maybe we need floating point specific implementations of some
> algorithms
>  to resolve this problem?
> 
>  It doesn’t seem like there is a way to provide the semantics required
> by
>  generic algorithms and still provide the expected behavior for
> floating
>  point values.
> 
> >>>
> >>> Well, what I'm trying to say is that generic algorithms such as
> >>> `index(of:)` require only an equivalence relation. For floating point
> >>> types, there are three ways to slice it:
> >>>
> >>> 1. NaN != NaN and +0 == -0 [what the traditional comparison operators
> are
> >>> constrained to do]
> >>> 2. NaN == NaN, +0 == -0, and the same number encoded different ways
> >>> compare equal
> >>> 3. NaN == NaN, +0 != -0, and the same number encoded different ways
> >>> compare not equal
> >>>
> >>> Both #2 and #3 can fall out of valid equivalence relations; if `===`
> >>> behaved like #2 for FloatingPoint types, then generic algorithms work
> just
> >>> fine. If we insist on using a total ordering defined by `<=>` all the
> time,
> >>> then we've got problems.
> >>>
> >>>
> >>> And if we don’t then we’re back to 3 different concepts of equality.
> >>> There is definitely a tradeoff no matter what we choose.
> >>>
> >>
> >> If some types have three concepts of equality, each with their
> particular
> >> use, why must we eliminate one of them?
> >>
> >>
> >> This isn’t about eliminating concepts of equality for a type.  They can
> >> have 42 if they want.
> >>
> >> This is about the right way to define the semantics of specific
> >> protocols.  It says nothing about additional notions of equality a type
> may
> >> have available.
> >>
> >> The difficulty is finding a design for the protocols that makes sense
> with
> >> floating point types because we want them to be able to conform to the
> >> protocols.
> >>
> >
> > Agreed. My argument is that if a Comparable can define its own `===`,
> still
> > supplying a valid equivalence relation but not being constrained by a
> > contract that `(a <=> b) == .same` iff `a === b`, then we are good to go
> > with floating point types.
>
> How would that work?  Can you spell out the implications, show how <=>
> and === would be implemented, and describe what it would mean for
> algorithms?
>

Right. I'm not married to this solution anymore, but I do think it could
work. There would still be a relationship required between `===` and `<=>`.
Namely:

`a === b` if `(a <=> b) == .same`

But for some values a and b, it is permitted that `a === b && (a <=> b) !=
.same`. That is, two identical values may be ordered in a total ordering
based on *inessential* qualities.
Generic algorithms that need to produce a stable ordering of elements will
use `<=>`. Those such as `index(of:)` will use `===` to test for identity.
Wouldn't that work?

>
> > On Jul 22, 2016, at 6:48 PM, Dave Abrahams via swift-evolution <
> > swift-evolution@swift.org> wrote:
> >
> >
> > on Fri Jul 22 2016, Jaden Geller  wrote:
> >
> > For floating point, I'd hope that `a === b` if `(a <=> b) == .same`
> > *but not iff*. This is to satisfy IEEE 754: "Comparisons shall
> > ignore the sign of zero (so +0 = −0)".
> >
> >
> > I don't see why both `(+0) === (-0)` and `(+0) <=> (-0)` can't return
> > `true` and `.same`, respectively. This doesn't break the total
> > ordering of values. `===` doesn't do raw memory comparison. They're
> > "identical", so it ought to return 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Matthew Johnson via swift-evolution

> On Jul 22, 2016, at 9:26 PM, Xiaodi Wu  wrote:
> 
> On Fri, Jul 22, 2016 at 9:23 PM, Matthew Johnson  > wrote:
> 
>> On Jul 22, 2016, at 9:17 PM, Xiaodi Wu > > wrote:
>> 
>> On Fri, Jul 22, 2016 at 9:15 PM, Matthew Johnson via swift-evolution 
>> > wrote:
>> 
>>> On Jul 22, 2016, at 9:04 PM, Dave Abrahams via swift-evolution 
>>> > wrote:
>>> 
>>> 
>>> on Fri Jul 22 2016, Matthew Johnson >> > wrote:
>>> 
> On Jul 22, 2016, at 8:37 PM, Xiaodi Wu via swift-evolution
> > wrote:
> 
> On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution
> 
 
> >>
> wrote:
> 
> on Fri Jul 22 2016, Daniel Duan  > wrote:
> 
>>> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution
>>> 
>>> >>
>>> wrote:
>>> 
>>> 
>>> on Fri Jul 22 2016, Daniel Duan
>>> 
>>> >
>>> 
>>> >> wrote:
>>> 
>> 
> On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
> 
> >
> 
>   wrote:
> 
> 
> on Thu Jul 21 2016, Duan
 
> 
> >
> 
> >>
> 
> >
> 
>  
> wrote:
> 
>> Great proposal. I want to second that areSame may mislead user to
>> think this is about identity.
>> 
>> I like areEquivalent() but there may be better names.
> 
> It really *is* about identity as I posted in a previous message.  But
> that doesn't change the fact that areEquivalent might be a better 
> name.
> It's one of the things we considered; it just seemed long for no real
> benefit.
> 
 
 If the addresses of the arguments aren’t being used, then we don’t 
 consider
 them part of their *identity*. I can follow this logic. My fear is 
 most users
 won’t make this leap on their own and get the same initial impression 
 as I did.
 It's entirely possible this fear is unfounded. Some educated 
 bikesheding
 wouldn't hurt here IMO :)
>>> 
>>> Well, it's still a very real question whether we ought to have the
>>> additional API surface implied by areSame, or wether we should collapse
>>> it with ===.
>>> 
>> 
>> To spell this out (because I had to think about it for a second): === 
>> will be derived from
>> <=>,
>> but also becomes default implementation for ==, which remains open for
>> customization.
> 
> I was imagining roughly this (untested):
> 
>  /// Two references are identical if they refer to the same
>  /// instance.
>  ///
>  /// - Note: Classes with a more-refined notion of “identical”
>  ///   should conform to `Identifiable` and implement `===`.
>  func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {
>ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
>  }
> 
>  /// Supports testing that two values of `Self` are identical
>  ///
>  /// If `a` and `b` are of type `Self`, `a === b` means that
>  /// `a` and `b` are interchangeable in most code.  A conforming
>  /// type can document 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Dave Abrahams via swift-evolution

on Fri Jul 22 2016, Xiaodi Wu  wrote:

> On Fri, Jul 22, 2016 at 9:13 PM, Matthew Johnson 
> wrote:
>
>>
>> On Jul 22, 2016, at 9:10 PM, Xiaodi Wu  wrote:
>>
>> On Fri, Jul 22, 2016 at 9:08 PM, Matthew Johnson 
>> wrote:
>>
>>>
>>> On Jul 22, 2016, at 9:04 PM, Xiaodi Wu  wrote:
>>>
>>> On Fri, Jul 22, 2016 at 8:57 PM, Matthew Johnson 
>>>  wrote:
>>>

 On Jul 22, 2016, at 8:54 PM, Xiaodi Wu via swift-evolution <
 swift-evolution@swift.org> wrote:

 On Fri, Jul 22, 2016 at 8:52 PM, Jaden Geller via swift-evolution <
 swift-evolution@swift.org> wrote:

> "The totalOrder predicate will order these cases, and it also
> distinguishes between different representations of NaNs and between the
> same decimal floating point number encoded in different ways."
> - [Wikipedia](
> https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate
> )
>
> Sounds like `===` should not return `true` for zeros of different
> signs, then.
>

 Fair enough; the result of that will be, as Pyry noted above, that:

 ```
 [-0.0, 1.0, .nan, 0.0].firstIndex(of: 0.0) //=> 3, not 0
 ```


 Maybe we need floating point specific implementations of some algorithms
 to resolve this problem?

 It doesn’t seem like there is a way to provide the semantics required by
 generic algorithms and still provide the expected behavior for floating
 point values.

>>>
>>> Well, what I'm trying to say is that generic algorithms such as
>>> `index(of:)` require only an equivalence relation. For floating point
>>> types, there are three ways to slice it:
>>>
>>> 1. NaN != NaN and +0 == -0 [what the traditional comparison operators are
>>> constrained to do]
>>> 2. NaN == NaN, +0 == -0, and the same number encoded different ways
>>> compare equal
>>> 3. NaN == NaN, +0 != -0, and the same number encoded different ways
>>> compare not equal
>>>
>>> Both #2 and #3 can fall out of valid equivalence relations; if `===`
>>> behaved like #2 for FloatingPoint types, then generic algorithms work just
>>> fine. If we insist on using a total ordering defined by `<=>` all the time,
>>> then we've got problems.
>>>
>>>
>>> And if we don’t then we’re back to 3 different concepts of equality.
>>> There is definitely a tradeoff no matter what we choose.
>>>
>>
>> If some types have three concepts of equality, each with their particular
>> use, why must we eliminate one of them?
>>
>>
>> This isn’t about eliminating concepts of equality for a type.  They can
>> have 42 if they want.
>>
>> This is about the right way to define the semantics of specific
>> protocols.  It says nothing about additional notions of equality a type may
>> have available.
>>
>> The difficulty is finding a design for the protocols that makes sense with
>> floating point types because we want them to be able to conform to the
>> protocols.
>>
>
> Agreed. My argument is that if a Comparable can define its own `===`, still
> supplying a valid equivalence relation but not being constrained by a
> contract that `(a <=> b) == .same` iff `a === b`, then we are good to go
> with floating point types.

How would that work?  Can you spell out the implications, show how <=>
and === would be implemented, and describe what it would mean for
algorithms?

>
> On Jul 22, 2016, at 6:48 PM, Dave Abrahams via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>
> on Fri Jul 22 2016, Jaden Geller  wrote:
>
> For floating point, I'd hope that `a === b` if `(a <=> b) == .same`
> *but not iff*. This is to satisfy IEEE 754: "Comparisons shall
> ignore the sign of zero (so +0 = −0)".
>
>
> I don't see why both `(+0) === (-0)` and `(+0) <=> (-0)` can't return
> `true` and `.same`, respectively. This doesn't break the total
> ordering of values. `===` doesn't do raw memory comparison. They're
> "identical", so it ought to return `true`.
>
>
> It ought to do whatever IEEE-754 specifies that its total ordering test
> does.  That is, IEEE-754 gets to decide whether the difference between
> +0 and -0 is “essential” to IEEE-754 floating point types, or not.
>
>
> On Jul 22, 2016, at 6:37 PM, Xiaodi Wu via swift-evolution
>  wrote:
>
> On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution
>  >>
> wrote:
>
> on Fri Jul 22 2016, Daniel Duan  > wrote:
>
> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution
>  >>
> wrote:
>
>
> on Fri Jul 22 2016, 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Matthew Johnson via swift-evolution

> On Jul 22, 2016, at 9:15 PM, Xiaodi Wu  wrote:
> 
> On Fri, Jul 22, 2016 at 9:13 PM, Matthew Johnson  > wrote:
> 
>> On Jul 22, 2016, at 9:10 PM, Xiaodi Wu > > wrote:
>> 
>> On Fri, Jul 22, 2016 at 9:08 PM, Matthew Johnson > > wrote:
>> 
>>> On Jul 22, 2016, at 9:04 PM, Xiaodi Wu >> > wrote:
>>> 
>>> On Fri, Jul 22, 2016 at 8:57 PM, Matthew Johnson >> > wrote:
>>> 
 On Jul 22, 2016, at 8:54 PM, Xiaodi Wu via swift-evolution 
 > wrote:
 
 On Fri, Jul 22, 2016 at 8:52 PM, Jaden Geller via swift-evolution 
 > wrote:
 "The totalOrder predicate will order these cases, and it also 
 distinguishes between different representations of NaNs and between the 
 same decimal floating point number encoded in different ways."
 - 
 [Wikipedia](https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate
  
 )
 
 Sounds like `===` should not return `true` for zeros of different signs, 
 then.
 
 Fair enough; the result of that will be, as Pyry noted above, that:
 
 ```
 [-0.0, 1.0, .nan, 0.0].firstIndex(of: 0.0) //=> 3, not 0
 ```
>>> 
>>> Maybe we need floating point specific implementations of some algorithms to 
>>> resolve this problem?
>>> 
>>> It doesn’t seem like there is a way to provide the semantics required by 
>>> generic algorithms and still provide the expected behavior for floating 
>>> point values.  
>>> 
>>> Well, what I'm trying to say is that generic algorithms such as 
>>> `index(of:)` require only an equivalence relation. For floating point 
>>> types, there are three ways to slice it:
>>> 
>>> 1. NaN != NaN and +0 == -0 [what the traditional comparison operators are 
>>> constrained to do]
>>> 2. NaN == NaN, +0 == -0, and the same number encoded different ways compare 
>>> equal
>>> 3. NaN == NaN, +0 != -0, and the same number encoded different ways compare 
>>> not equal
>>> 
>>> Both #2 and #3 can fall out of valid equivalence relations; if `===` 
>>> behaved like #2 for FloatingPoint types, then generic algorithms work just 
>>> fine. If we insist on using a total ordering defined by `<=>` all the time, 
>>> then we've got problems.
>> 
>> And if we don’t then we’re back to 3 different concepts of equality.  There 
>> is definitely a tradeoff no matter what we choose.
>> 
>> If some types have three concepts of equality, each with their particular 
>> use, why must we eliminate one of them?
> 
> This isn’t about eliminating concepts of equality for a type.  They can have 
> 42 if they want.  
> 
> This is about the right way to define the semantics of specific protocols.  
> It says nothing about additional notions of equality a type may have 
> available.
> 
> The difficulty is finding a design for the protocols that makes sense with 
> floating point types because we want them to be able to conform to the 
> protocols.
> 
> 
> Agreed. My argument is that if a Comparable can define its own `===`, still 
> supplying a valid equivalence relation but not being constrained by a 
> contract that `(a <=> b) == .same` iff `a === b`, then we are good to go with 
> floating point types.

At the expense of `===` that introduces a new concept of floating point 
identity as well as the burden of a more complex design for the protocols.  

How does generic code decide when to use `===` and when to use `<=>` and what 
the implications of that choice are for arbitrary types?

> 
> On Jul 22, 2016, at 6:48 PM, Dave Abrahams via swift-evolution 
> > wrote:
> 
> 
> on Fri Jul 22 2016, Jaden Geller  > wrote:
> 
>>> For floating point, I'd hope that `a === b` if `(a <=> b) == .same`
>>> *but not iff*. This is to satisfy IEEE 754: "Comparisons shall
>>> ignore the sign of zero (so +0 = −0)".
>> 
>> I don't see why both `(+0) === (-0)` and `(+0) <=> (-0)` can't return
>> `true` and `.same`, respectively. This doesn't break the total
>> ordering of values. `===` doesn't do raw memory comparison. They're
>> "identical", so it ought to return `true`.
> 
> It ought to do whatever IEEE-754 specifies that its total ordering test
> does.  That is, IEEE-754 gets to decide whether the difference between
> +0 and -0 is “essential” to IEEE-754 floating point types, or not.
> 
>> 
>>> On Jul 22, 2016, at 6:37 PM, Xiaodi Wu via 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Matthew Johnson via swift-evolution

> On Jul 22, 2016, at 9:24 PM, Dave Abrahams  wrote:
> 
> 
> on Fri Jul 22 2016, Matthew Johnson  wrote:
> 
>>> On Jul 22, 2016, at 9:04 PM, Dave Abrahams via swift-evolution 
>>>  wrote:
>>> 
>>> 
>>> on Fri Jul 22 2016, Matthew Johnson >> > wrote:
>>> 
>> 
> On Jul 22, 2016, at 8:37 PM, Xiaodi Wu via swift-evolution
> > wrote:
> 
> On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution
> 
 
> >>
> wrote:
> 
> on Fri Jul 22 2016, Daniel Duan  > wrote:
> 
>>> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution
>>> 
>>> >>
>>> wrote:
>>> 
>>> 
>>> on Fri Jul 22 2016, Daniel Duan
>>> 
>>> >
>>> 
>>> >> wrote:
>>> 
>> 
> On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
> 
> >
> 
>   wrote:
> 
> 
> on Thu Jul 21 2016, Duan
 
> 
> >
> 
> >>
> 
> >
> 
>  
> wrote:
> 
>> Great proposal. I want to second that areSame may mislead user to
>> think this is about identity.
>> 
>> I like areEquivalent() but there may be better names.
> 
> It really *is* about identity as I posted in a previous message.  But
> that doesn't change the fact that areEquivalent might be a better 
> name.
> It's one of the things we considered; it just seemed long for no real
> benefit.
> 
 
 If the addresses of the arguments aren’t being used, then we don’t 
 consider
 them part of their *identity*. I can follow this logic. My fear is 
 most users
 won’t make this leap on their own and get the same initial impression 
 as I did.
 It's entirely possible this fear is unfounded. Some educated 
 bikesheding
 wouldn't hurt here IMO :)
>>> 
>>> Well, it's still a very real question whether we ought to have the
>>> additional API surface implied by areSame, or wether we should collapse
>>> it with ===.
>>> 
>> 
>> To spell this out (because I had to think about it for a second): === 
>> will be derived from
>> <=>,
>> but also becomes default implementation for ==, which remains open for
>> customization.
> 
> I was imagining roughly this (untested):
> 
> /// Two references are identical if they refer to the same
> /// instance.
> ///
> /// - Note: Classes with a more-refined notion of “identical”
> ///   should conform to `Identifiable` and implement `===`.
> func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {
>   ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
> }
> 
> /// Supports testing that two values of `Self` are identical
> ///
> /// If `a` and `b` are of type `Self`, `a === b` means that
> /// `a` and `b` are interchangeable in most code.  A conforming
> /// type can document that specific observable characteristics
> /// (such as the `capacity` of an `Array`) are inessential and
> /// thus not to be considered as part of the interchangeability
> /// guarantee.
> ///
> /// - Requires: `===` induces an equivalence relation over
> ///   instances.
> /// - Note: conforming types will gain an `==` operator that

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Matthew Johnson via swift-evolution

> On Jul 22, 2016, at 9:20 PM, Xiaodi Wu  wrote:
> 
> On Fri, Jul 22, 2016 at 9:19 PM, Matthew Johnson  > wrote:
> 
>> On Jul 22, 2016, at 9:12 PM, Xiaodi Wu > > wrote:
>> 
>> On Fri, Jul 22, 2016 at 9:09 PM, Jaden Geller > > wrote:
>>> 1. NaN != NaN and +0 == -0 [what the traditional comparison operators are 
>>> constrained to do]
>>> 2. NaN == NaN, +0 == -0, and the same number encoded different ways compare 
>>> equal
>>> 3. NaN == NaN, +0 != -0, and the same number encoded different ways compare 
>>> not equal
>> 
>> 
>> Though it seems super confusing that a language have THREE ways to compare 
>> values, that does almost seem necessary here. Do we actually need an 
>> operator that performs #3? I understand that that is equality under total 
>> ordering, but couldn't users just write `(a <=> b) == .same` if they want 
>> that?
>> 
>> For floating point types, I think `===` shouldn't be #3. From a practical 
>> standpoint, no one ever wants that definition unless they are ordering 
>> things. Whereas you'd want #2 for things like `.index(of:)` and #1 for the 
>> traditional comparison operators.
> 
> However, we have to introduce a new notion of identity for floating point 
> types if `===` isn’t #3.  Floating points are tricky enough already.  Is that 
> really a good thing?
> 
> Further, it encodes three separate meanings of equality in the protocols.  We 
> should avoid that if we can.
> 
> It feels like maybe the right solution is floating point specific algorithm 
> overloads.  It doesn’t seem like too big a surprise that this is the case 
> when you really dig into the details.
> 
> 
> I see what you're getting at here. But I like your other alternative better, 
> which is to define identity in a generically useful way for floating point 
> types, and preserve IEEE semantics in its own method for floating point types.

That wasn’t actually my idea - it was yours! :)  

> 
>>> On Jul 22, 2016, at 7:04 PM, Xiaodi Wu >> > wrote:
>>> 
>>> On Fri, Jul 22, 2016 at 8:57 PM, Matthew Johnson >> > wrote:
>>> 
 On Jul 22, 2016, at 8:54 PM, Xiaodi Wu via swift-evolution 
 > wrote:
 
 On Fri, Jul 22, 2016 at 8:52 PM, Jaden Geller via swift-evolution 
 > wrote:
 "The totalOrder predicate will order these cases, and it also 
 distinguishes between different representations of NaNs and between the 
 same decimal floating point number encoded in different ways."
 - 
 [Wikipedia](https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate
  
 )
 
 Sounds like `===` should not return `true` for zeros of different signs, 
 then.
 
 Fair enough; the result of that will be, as Pyry noted above, that:
 
 ```
 [-0.0, 1.0, .nan, 0.0].firstIndex(of: 0.0) //=> 3, not 0
 ```
>>> 
>>> Maybe we need floating point specific implementations of some algorithms to 
>>> resolve this problem?
>>> 
>>> It doesn’t seem like there is a way to provide the semantics required by 
>>> generic algorithms and still provide the expected behavior for floating 
>>> point values.  
>>> 
>>> Well, what I'm trying to say is that generic algorithms such as 
>>> `index(of:)` require only an equivalence relation. For floating point 
>>> types, there are three ways to slice it:
>>> 
>>> 1. NaN != NaN and +0 == -0 [what the traditional comparison operators are 
>>> constrained to do]
>>> 2. NaN == NaN, +0 == -0, and the same number encoded different ways compare 
>>> equal
>>> 3. NaN == NaN, +0 != -0, and the same number encoded different ways compare 
>>> not equal
>>> 
>>> Both #2 and #3 can fall out of valid equivalence relations; if `===` 
>>> behaved like #2 for FloatingPoint types, then generic algorithms work just 
>>> fine. If we insist on using a total ordering defined by `<=>` all the time, 
>>> then we've got problems.
>>> 
>>>  
>>> 
 
> On Jul 22, 2016, at 6:48 PM, Dave Abrahams via swift-evolution 
> > wrote:
> 
> 
> on Fri Jul 22 2016, Jaden Geller  > wrote:
> 
>>> For floating point, I'd hope that `a === b` if `(a <=> b) == .same`
>>> *but not iff*. This is to satisfy IEEE 754: "Comparisons shall
>>> ignore the sign of zero (so +0 = −0)".
>> 
>> I don't see why both `(+0) === (-0)` and `(+0) <=> (-0)` can't return
>> `true` and `.same`, respectively. This doesn't break the 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Dave Abrahams via swift-evolution

on Fri Jul 22 2016, Matthew Johnson  wrote:

>> On Jul 22, 2016, at 9:04 PM, Dave Abrahams via swift-evolution 
>>  wrote:
>> 
>> 
>> on Fri Jul 22 2016, Matthew Johnson > > wrote:
>> 
>
 On Jul 22, 2016, at 8:37 PM, Xiaodi Wu via swift-evolution
 > wrote:
 
 On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution
 
>>> 
 >>
 wrote:
 
 on Fri Jul 22 2016, Daniel Duan >>> > wrote:
 
>> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution
>> 
>> >>
>> wrote:
>> 
>> 
>> on Fri Jul 22 2016, Daniel Duan
>> 
>> >
>> 
>> > wrote:
>> 
> 
 On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
 
 >
 
 >> 
 
 >
 
 >>
 
 >
 
 
 wrote:
 
> Great proposal. I want to second that areSame may mislead user to
> think this is about identity.
> 
> I like areEquivalent() but there may be better names.
 
 It really *is* about identity as I posted in a previous message.  But
 that doesn't change the fact that areEquivalent might be a better name.
 It's one of the things we considered; it just seemed long for no real
 benefit.
 
>>> 
>>> If the addresses of the arguments aren’t being used, then we don’t 
>>> consider
>>> them part of their *identity*. I can follow this logic. My fear is most 
>>> users
>>> won’t make this leap on their own and get the same initial impression 
>>> as I did.
>>> It's entirely possible this fear is unfounded. Some educated bikesheding
>>> wouldn't hurt here IMO :)
>> 
>> Well, it's still a very real question whether we ought to have the
>> additional API surface implied by areSame, or wether we should collapse
>> it with ===.
>> 
> 
> To spell this out (because I had to think about it for a second): === 
> will be derived from
> <=>,
> but also becomes default implementation for ==, which remains open for
> customization.
 
 I was imagining roughly this (untested):
 
  /// Two references are identical if they refer to the same
  /// instance.
  ///
  /// - Note: Classes with a more-refined notion of “identical”
  ///   should conform to `Identifiable` and implement `===`.
  func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {
ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
  }
 
  /// Supports testing that two values of `Self` are identical
  ///
  /// If `a` and `b` are of type `Self`, `a === b` means that
  /// `a` and `b` are interchangeable in most code.  A conforming
  /// type can document that specific observable characteristics
  /// (such as the `capacity` of an `Array`) are inessential and
  /// thus not to be considered as part of the interchangeability
  /// guarantee.
  ///
  /// - Requires: `===` induces an equivalence relation over
  ///   instances.
  /// - Note: conforming types will gain an `==` operator that
  ///   forwards to `===`.
  /// - Note: Types that require domain-specific `==`
  ///   implementations with different semantics (e.g. floating
  ///   point) should define a more-specific 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Dave Abrahams via swift-evolution

on Fri Jul 22 2016, Brent Royal-Gordon  wrote:

>> On Jul 22, 2016, at 4:55 PM, Daniel Duan via swift-evolution 
>>  wrote:
>> 
>>> Well, it's still a very real question whether we ought to have the
>>> additional API surface implied by areSame, or wether we should collapse
>>> it with ===.
>>> 
>> 
>> To spell this out (because I had to think about it for a second): === will 
>> be derived from
>> <=>, but also becomes default implementation for ==, which remains open for 
>> customization.
>> 
>> I like this idea. If we keep === as a separate thing, now users have 3 
>> “opportunities” to define
>> equality. The must be few, if any, use cases for this.
>> 
>> Would love to see if anyone on the list can give us an example. Otherwise we 
>> should make
>> areSame === again™!
>
> If `===` is the new `areSame`, and `Hashable` is based on `===`,
> wouldn't that mean that objects could only be hashed (and thus, be
> looked up in Dictionary and Set) by identity? So, for instance, code
> like this:
>
>   var set = Set()
>
>   set.insert("test")
>   set.insert("test")
>
>   print(set.count)
>
> Would print "2"? Or worse, might print "1" or "2" depending on the
> details of how Swift generates literals and Foundation implements
> short strings?
>
> Am I the only one who thinks that's a problem?

No, NSString's conformance to Identifiable (probably NSObject's,
actually) would define `===` in terms of `isEqual()`.  That's saying
identity for these types is determined by `isEqual()`.

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


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Xiaodi Wu via swift-evolution
On Fri, Jul 22, 2016 at 9:19 PM, Matthew Johnson 
wrote:

>
> On Jul 22, 2016, at 9:12 PM, Xiaodi Wu  wrote:
>
> On Fri, Jul 22, 2016 at 9:09 PM, Jaden Geller 
> wrote:
>
>> 1. NaN != NaN and +0 == -0 [what the traditional comparison operators are
>> constrained to do]
>> 2. NaN == NaN, +0 == -0, and the same number encoded different ways
>> compare equal
>> 3. NaN == NaN, +0 != -0, and the same number encoded different ways
>> compare not equal
>>
>>
>> Though it seems super confusing that a language have THREE ways to
>> compare values, that does almost seem necessary here. Do we actually need
>> an operator that performs #3? I understand that that is equality under
>> total ordering, but couldn't users just write `(a <=> b) == .same` if they
>> want that?
>>
>
> For floating point types, I think `===` shouldn't be #3. From a practical
> standpoint, no one ever wants that definition unless they are ordering
> things. Whereas you'd want #2 for things like `.index(of:)` and #1 for the
> traditional comparison operators.
>
>
> However, we have to introduce a new notion of identity for floating point
> types if `===` isn’t #3.  Floating points are tricky enough already.  Is
> that really a good thing?
>
> Further, it encodes three separate meanings of equality in the protocols.
> We should avoid that if we can.
>
> It feels like maybe the right solution is floating point specific
> algorithm overloads.  It doesn’t seem like too big a surprise that this is
> the case when you really dig into the details.
>


I see what you're getting at here. But I like your other alternative
better, which is to define identity in a generically useful way for
floating point types, and preserve IEEE semantics in its own method for
floating point types.

On Jul 22, 2016, at 7:04 PM, Xiaodi Wu  wrote:
>>
>> On Fri, Jul 22, 2016 at 8:57 PM, Matthew Johnson 
>>  wrote:
>>
>>>
>>> On Jul 22, 2016, at 8:54 PM, Xiaodi Wu via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
>>> On Fri, Jul 22, 2016 at 8:52 PM, Jaden Geller via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
 "The totalOrder predicate will order these cases, and it also
 distinguishes between different representations of NaNs and between the
 same decimal floating point number encoded in different ways."
 - [Wikipedia](
 https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate
 )

 Sounds like `===` should not return `true` for zeros of different
 signs, then.

>>>
>>> Fair enough; the result of that will be, as Pyry noted above, that:
>>>
>>> ```
>>> [-0.0, 1.0, .nan, 0.0].firstIndex(of: 0.0) //=> 3, not 0
>>> ```
>>>
>>>
>>> Maybe we need floating point specific implementations of some algorithms
>>> to resolve this problem?
>>>
>>> It doesn’t seem like there is a way to provide the semantics required by
>>> generic algorithms and still provide the expected behavior for floating
>>> point values.
>>>
>>
>> Well, what I'm trying to say is that generic algorithms such as
>> `index(of:)` require only an equivalence relation. For floating point
>> types, there are three ways to slice it:
>>
>> 1. NaN != NaN and +0 == -0 [what the traditional comparison operators are
>> constrained to do]
>> 2. NaN == NaN, +0 == -0, and the same number encoded different ways
>> compare equal
>> 3. NaN == NaN, +0 != -0, and the same number encoded different ways
>> compare not equal
>>
>> Both #2 and #3 can fall out of valid equivalence relations; if `===`
>> behaved like #2 for FloatingPoint types, then generic algorithms work just
>> fine. If we insist on using a total ordering defined by `<=>` all the time,
>> then we've got problems.
>>
>>
>>
>>>
>>>
>>> On Jul 22, 2016, at 6:48 PM, Dave Abrahams via swift-evolution <
 swift-evolution@swift.org> wrote:


 on Fri Jul 22 2016, Jaden Geller  wrote:

 For floating point, I'd hope that `a === b` if `(a <=> b) == .same`
 *but not iff*. This is to satisfy IEEE 754: "Comparisons shall
 ignore the sign of zero (so +0 = −0)".


 I don't see why both `(+0) === (-0)` and `(+0) <=> (-0)` can't return
 `true` and `.same`, respectively. This doesn't break the total
 ordering of values. `===` doesn't do raw memory comparison. They're
 "identical", so it ought to return `true`.


 It ought to do whatever IEEE-754 specifies that its total ordering test
 does.  That is, IEEE-754 gets to decide whether the difference between
 +0 and -0 is “essential” to IEEE-754 floating point types, or not.


 On Jul 22, 2016, at 6:37 PM, Xiaodi Wu via swift-evolution
  wrote:

 On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution
 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Dave Abrahams via swift-evolution

on Fri Jul 22 2016, Xiaodi Wu  wrote:

> On Fri, Jul 22, 2016 at 8:45 PM, Dave Abrahams  wrote:
>
>>
>> on Fri Jul 22 2016, Xiaodi Wu  wrote:
>>
>> > On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution <
>> > swift-evolution@swift.org> wrote:
>> >
>> >>
>> >> on Fri Jul 22 2016, Daniel Duan  wrote:
>> >>
>> >> >> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution <
>> >> swift-evolution@swift.org> wrote:
>> >> >>
>> >> >>
>> >> >> on Fri Jul 22 2016, Daniel Duan  >> swift-evolution@swift.org>> wrote:
>> >> >>
>> >> >
>> >>  On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
>> >>  > >>  >
>> wrote:
>> >> 
>> >> 
>> >>  on Thu Jul 21 2016, Duan
>> >> >>>
>> >>  > >>  
>> >>   swift-evolution@swift.org
>> >> >>>
>> >>  wrote:
>> >> 
>> >> > Great proposal. I want to second that areSame may mislead user to
>> >> > think this is about identity.
>> >> >
>> >> > I like areEquivalent() but there may be better names.
>> >> 
>> >>  It really *is* about identity as I posted in a previous message.
>> But
>> >>  that doesn't change the fact that areEquivalent might be a better
>> >> name.
>> >>  It's one of the things we considered; it just seemed long for no
>> real
>> >>  benefit.
>> >> 
>> >> >>>
>> >> >>> If the addresses of the arguments aren’t being used, then we don’t
>> >> consider
>> >> >>> them part of their *identity*. I can follow this logic. My fear is
>> >> most users
>> >> >>> won’t make this leap on their own and get the same initial
>> impression
>> >> as I did.
>> >> >>> It's entirely possible this fear is unfounded. Some educated
>> >> bikesheding
>> >> >>> wouldn't hurt here IMO :)
>> >> >>
>> >> >> Well, it's still a very real question whether we ought to have the
>> >> >> additional API surface implied by areSame, or wether we should
>> collapse
>> >> >> it with ===.
>> >> >>
>> >> >
>> >> > To spell this out (because I had to think about it for a second): ===
>> >> will be derived from
>> >> > <=>,
>> >> > but also becomes default implementation for ==, which remains open for
>> >> > customization.
>> >>
>> >> I was imagining roughly this (untested):
>> >>
>> >>   /// Two references are identical if they refer to the same
>> >>   /// instance.
>> >>   ///
>> >>   /// - Note: Classes with a more-refined notion of “identical”
>> >>   ///   should conform to `Identifiable` and implement `===`.
>> >>   func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {
>> >> ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
>> >>   }
>> >>
>> >>   /// Supports testing that two values of `Self` are identical
>> >>   ///
>> >>   /// If `a` and `b` are of type `Self`, `a === b` means that
>> >>   /// `a` and `b` are interchangeable in most code.  A conforming
>> >>   /// type can document that specific observable characteristics
>> >>   /// (such as the `capacity` of an `Array`) are inessential and
>> >>   /// thus not to be considered as part of the interchangeability
>> >>   /// guarantee.
>> >>   ///
>> >>   /// - Requires: `===` induces an equivalence relation over
>> >>   ///   instances.
>> >>   /// - Note: conforming types will gain an `==` operator that
>> >>   ///   forwards to `===`.
>> >>   /// - Note: Types that require domain-specific `==`
>> >>   ///   implementations with different semantics (e.g. floating
>> >>   ///   point) should define a more-specific overload of `==`,
>> >>   ///   which will be used in contexts where the static type is
>> >>   ///   known to the compiler.
>> >>   /// - Note: Generic code should usually use `==` to compare
>> >>   ///   conforming instances; that will always dispatch to `===`
>> >>   ///   and will be unaffected by more specific overloads of
>> >>   ///   `==`.
>> >>   protocol Identifiable { // née Equatable name is negotiable
>> >> func ===(_: Self, _: aSelf) -> Bool
>> >>   }
>> >>
>> >>   /// Default definition of `==` for Identifiable types.
>> >>   func ==(lhs: T, rhs: T) -> Bool {
>> >> return lhs === rhs
>> >>   }
>> >>
>> >>   /// Conforming types have a default total ordering.
>> >>   ///
>> >>   /// If `a` and `b` are of type `Self`, `a <=> b` means that
>> >>   /// `a` and `b` are interchangeable in most code.  A conforming
>> >>   /// type can document that specific observable characteristics
>> >>   /// (such as the `capacity` of an `Array`) are inessential and
>> >>   /// thus not to be considered as part of the interchangeability
>> >>   /// guarantee.
>> >>   ///
>> >>   /// - Requires: `<=>` induces a total ordering over
>> >>   ///   instances.
>> >>   /// - Requires: the semantics of `<=>` are  consistent with
>> >>   ///   those of `===`.  That is, `(a <=> b) == .equivalent`
>> >>  

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Xiaodi Wu via swift-evolution
On Fri, Jul 22, 2016 at 9:15 PM, Matthew Johnson via swift-evolution <
swift-evolution@swift.org> wrote:

>
> On Jul 22, 2016, at 9:04 PM, Dave Abrahams via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>
> on Fri Jul 22 2016, Matthew Johnson  wrote:
>
> On Jul 22, 2016, at 8:37 PM, Xiaodi Wu via swift-evolution
>  wrote:
>
> On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution
> 
>
> >>
> wrote:
>
> on Fri Jul 22 2016, Daniel Duan  > wrote:
>
> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution
>  >>
> wrote:
>
>
> on Fri Jul 22 2016, Daniel Duan
>  >
> 
>  wrote:
>
>
> On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
>  >
> 
>  wrote:
>
>
> on Thu Jul 21 2016, Duan
>
>
>  >
> 
> >>
> 
> >
> 
> 
> wrote:
>
> Great proposal. I want to second that areSame may mislead user to
> think this is about identity.
>
> I like areEquivalent() but there may be better names.
>
>
> It really *is* about identity as I posted in a previous message.  But
> that doesn't change the fact that areEquivalent might be a better name.
> It's one of the things we considered; it just seemed long for no real
> benefit.
>
>
> If the addresses of the arguments aren’t being used, then we don’t consider
> them part of their *identity*. I can follow this logic. My fear is most
> users
> won’t make this leap on their own and get the same initial impression as I
> did.
> It's entirely possible this fear is unfounded. Some educated bikesheding
> wouldn't hurt here IMO :)
>
>
> Well, it's still a very real question whether we ought to have the
> additional API surface implied by areSame, or wether we should collapse
> it with ===.
>
>
> To spell this out (because I had to think about it for a second): === will
> be derived from
> <=>,
> but also becomes default implementation for ==, which remains open for
> customization.
>
>
> I was imagining roughly this (untested):
>
>  /// Two references are identical if they refer to the same
>  /// instance.
>  ///
>  /// - Note: Classes with a more-refined notion of “identical”
>  ///   should conform to `Identifiable` and implement `===`.
>  func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {
>ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
>  }
>
>  /// Supports testing that two values of `Self` are identical
>  ///
>  /// If `a` and `b` are of type `Self`, `a === b` means that
>  /// `a` and `b` are interchangeable in most code.  A conforming
>  /// type can document that specific observable characteristics
>  /// (such as the `capacity` of an `Array`) are inessential and
>  /// thus not to be considered as part of the interchangeability
>  /// guarantee.
>  ///
>  /// - Requires: `===` induces an equivalence relation over
>  ///   instances.
>  /// - Note: conforming types will gain an `==` operator that
>  ///   forwards to `===`.
>  /// - Note: Types that require domain-specific `==`
>  ///   implementations with different semantics (e.g. floating
>  ///   point) should define a more-specific overload of `==`,
>  ///   which will be used in contexts where the static type is
>  ///   known to the compiler.
>  /// - Note: Generic code should usually use `==` to compare
>  ///   conforming instances; that will always dispatch to `===`
>  ///   and will be unaffected by more specific overloads of
>  ///   `==`.
>  protocol Identifiable { // née Equatable name is negotiable
>func ===(_: Self, _: aSelf) -> Bool
>  }
>
>  /// Default definition of `==` for Identifiable types.
>  func ==(lhs: T, rhs: T) -> Bool {
>return lhs === rhs
>  }
>
>  /// Conforming types have a default total ordering.
>  ///
>  /// If `a` and `b` are of type `Self`, `a <=> b` means that
>  /// `a` and `b` are interchangeable in most code.  A conforming
>  /// type can document that specific observable characteristics
>  /// (such as the 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Dave Abrahams via swift-evolution

on Fri Jul 22 2016, Jaden Geller  wrote:

> "The totalOrder predicate will order these cases, and it also
> distinguishes between different representations of NaNs and between
> the same decimal floating point number encoded in different ways."
> - 
> [Wikipedia](https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate)
>
> Sounds like `===` should not return `true` for zeros of different signs, then.

Right.

>> On Jul 22, 2016, at 6:48 PM, Dave Abrahams via swift-evolution
>>  wrote:
>> 
>> 
>> on Fri Jul 22 2016, Jaden Geller
>> > >
>> wrote:
>> 
 For floating point, I'd hope that `a === b` if `(a <=> b) == .same`
 *but not iff*. This is to satisfy IEEE 754: "Comparisons shall
 ignore the sign of zero (so +0 = −0)".
>>> 
>>> I don't see why both `(+0) === (-0)` and `(+0) <=> (-0)` can't return
>>> `true` and `.same`, respectively. This doesn't break the total
>>> ordering of values. `===` doesn't do raw memory comparison. They're
>>> "identical", so it ought to return `true`.
>> 
>> It ought to do whatever IEEE-754 specifies that its total ordering test
>> does.  That is, IEEE-754 gets to decide whether the difference between
>> +0 and -0 is “essential” to IEEE-754 floating point types, or not.
>> 
>>> 
 On Jul 22, 2016, at 6:37 PM, Xiaodi Wu via swift-evolution
 >
 wrote:
 
 On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution
 
 >>
 wrote:
 
 on Fri Jul 22 2016, Daniel Duan >>> > wrote:
 
>> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution
>> > 
>> > >>
>> wrote:
>> 
>> 
>> on Fri Jul 22 2016, Daniel Duan
>> > 
>> > >
>> > 
>> > > wrote:
>> 
> 
 On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
 
 >
 
 >> 
 
 >
 
 >>
 
 >
 
 
 wrote:
 
> Great proposal. I want to second that areSame may mislead user to
> think this is about identity.
> 
> I like areEquivalent() but there may be better names.
 
 It really *is* about identity as I posted in a previous message.  But
 that doesn't change the fact that areEquivalent might be a better name.
 It's one of the things we considered; it just seemed long for no real
 benefit.
 
>>> 
>>> If the addresses of the arguments aren’t being used, then we don’t 
>>> consider
>>> them part of their *identity*. I can follow this logic. My fear is most 
>>> users
>>> won’t make this leap on their own and get the same initial impression 
>>> as I did.
>>> It's entirely possible this fear is unfounded. Some educated bikesheding
>>> wouldn't hurt here IMO :)
>> 
>> Well, it's still a very real question whether we ought to have the
>> additional API surface implied by areSame, or wether we should collapse
>> it with ===.
>> 
> 
> To spell this out (because I had to think about it for a second): === 
> will be derived from
> <=>,
> but also becomes default implementation for ==, which remains open for

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Xiaodi Wu via swift-evolution
On Fri, Jul 22, 2016 at 9:13 PM, Matthew Johnson 
wrote:

>
> On Jul 22, 2016, at 9:10 PM, Xiaodi Wu  wrote:
>
> On Fri, Jul 22, 2016 at 9:08 PM, Matthew Johnson 
> wrote:
>
>>
>> On Jul 22, 2016, at 9:04 PM, Xiaodi Wu  wrote:
>>
>> On Fri, Jul 22, 2016 at 8:57 PM, Matthew Johnson 
>>  wrote:
>>
>>>
>>> On Jul 22, 2016, at 8:54 PM, Xiaodi Wu via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
>>> On Fri, Jul 22, 2016 at 8:52 PM, Jaden Geller via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
 "The totalOrder predicate will order these cases, and it also
 distinguishes between different representations of NaNs and between the
 same decimal floating point number encoded in different ways."
 - [Wikipedia](
 https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate
 )

 Sounds like `===` should not return `true` for zeros of different
 signs, then.

>>>
>>> Fair enough; the result of that will be, as Pyry noted above, that:
>>>
>>> ```
>>> [-0.0, 1.0, .nan, 0.0].firstIndex(of: 0.0) //=> 3, not 0
>>> ```
>>>
>>>
>>> Maybe we need floating point specific implementations of some algorithms
>>> to resolve this problem?
>>>
>>> It doesn’t seem like there is a way to provide the semantics required by
>>> generic algorithms and still provide the expected behavior for floating
>>> point values.
>>>
>>
>> Well, what I'm trying to say is that generic algorithms such as
>> `index(of:)` require only an equivalence relation. For floating point
>> types, there are three ways to slice it:
>>
>> 1. NaN != NaN and +0 == -0 [what the traditional comparison operators are
>> constrained to do]
>> 2. NaN == NaN, +0 == -0, and the same number encoded different ways
>> compare equal
>> 3. NaN == NaN, +0 != -0, and the same number encoded different ways
>> compare not equal
>>
>> Both #2 and #3 can fall out of valid equivalence relations; if `===`
>> behaved like #2 for FloatingPoint types, then generic algorithms work just
>> fine. If we insist on using a total ordering defined by `<=>` all the time,
>> then we've got problems.
>>
>>
>> And if we don’t then we’re back to 3 different concepts of equality.
>> There is definitely a tradeoff no matter what we choose.
>>
>
> If some types have three concepts of equality, each with their particular
> use, why must we eliminate one of them?
>
>
> This isn’t about eliminating concepts of equality for a type.  They can
> have 42 if they want.
>
> This is about the right way to define the semantics of specific
> protocols.  It says nothing about additional notions of equality a type may
> have available.
>
> The difficulty is finding a design for the protocols that makes sense with
> floating point types because we want them to be able to conform to the
> protocols.
>


Agreed. My argument is that if a Comparable can define its own `===`, still
supplying a valid equivalence relation but not being constrained by a
contract that `(a <=> b) == .same` iff `a === b`, then we are good to go
with floating point types.

On Jul 22, 2016, at 6:48 PM, Dave Abrahams via swift-evolution <
 swift-evolution@swift.org> wrote:


 on Fri Jul 22 2016, Jaden Geller  wrote:

 For floating point, I'd hope that `a === b` if `(a <=> b) == .same`
 *but not iff*. This is to satisfy IEEE 754: "Comparisons shall
 ignore the sign of zero (so +0 = −0)".


 I don't see why both `(+0) === (-0)` and `(+0) <=> (-0)` can't return
 `true` and `.same`, respectively. This doesn't break the total
 ordering of values. `===` doesn't do raw memory comparison. They're
 "identical", so it ought to return `true`.


 It ought to do whatever IEEE-754 specifies that its total ordering test
 does.  That is, IEEE-754 gets to decide whether the difference between
 +0 and -0 is “essential” to IEEE-754 floating point types, or not.


 On Jul 22, 2016, at 6:37 PM, Xiaodi Wu via swift-evolution
  wrote:

 On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution
 >>
 wrote:

 on Fri Jul 22 2016, Daniel Duan >>> > wrote:

 On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution
 >>
 wrote:


 on Fri Jul 22 2016, Daniel Duan
 >
 
 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Dave Abrahams via swift-evolution

on Fri Jul 22 2016, Matthew Johnson  wrote:

>> On Jul 22, 2016, at 8:37 PM, Xiaodi Wu via swift-evolution
>>  wrote:
>> 
>> On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution
>> 
>> >
>> wrote:
>> 
>> on Fri Jul 22 2016, Daniel Duan  wrote:
>> 
>> >> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution
>> >> > >> >
>> >> wrote:
>> >>
>> >>
>> >> on Fri Jul 22 2016, Daniel Duan
>> >> > >> 
>> >> > >> >>
>> >> wrote:
>> >>
>> >
>>  On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
>>  >  
>>  >  >>
>>  wrote:
>> 
>> 
>>  on Thu Jul 21 2016, Duan
>> >>>
>>  >  
>>  >  >
>>  >  
>>  >  >  wrote:
>> 
>> > Great proposal. I want to second that areSame may mislead user to
>> > think this is about identity.
>> >
>> > I like areEquivalent() but there may be better names.
>> 
>>  It really *is* about identity as I posted in a previous message.  But
>>  that doesn't change the fact that areEquivalent might be a better name.
>>  It's one of the things we considered; it just seemed long for no real
>>  benefit.
>> 
>> >>>
>> >>> If the addresses of the arguments aren’t being used, then we don’t 
>> >>> consider
>> >>> them part of their *identity*. I can follow this logic. My fear is most 
>> >>> users
>> >>> won’t make this leap on their own and get the same initial impression as 
>> >>> I did.
>> >>> It's entirely possible this fear is unfounded. Some educated bikesheding
>> >>> wouldn't hurt here IMO :)
>> >>
>> >> Well, it's still a very real question whether we ought to have the
>> >> additional API surface implied by areSame, or wether we should collapse
>> >> it with ===.
>> >>
>> >
>> > To spell this out (because I had to think about it for a second): === will 
>> > be derived from
>> > <=>,
>> > but also becomes default implementation for ==, which remains open for
>> > customization.
>> 
>> I was imagining roughly this (untested):
>> 
>>   /// Two references are identical if they refer to the same
>>   /// instance.
>>   ///
>>   /// - Note: Classes with a more-refined notion of “identical”
>>   ///   should conform to `Identifiable` and implement `===`.
>>   func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {
>> ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
>>   }
>> 
>>   /// Supports testing that two values of `Self` are identical
>>   ///
>>   /// If `a` and `b` are of type `Self`, `a === b` means that
>>   /// `a` and `b` are interchangeable in most code.  A conforming
>>   /// type can document that specific observable characteristics
>>   /// (such as the `capacity` of an `Array`) are inessential and
>>   /// thus not to be considered as part of the interchangeability
>>   /// guarantee.
>>   ///
>>   /// - Requires: `===` induces an equivalence relation over
>>   ///   instances.
>>   /// - Note: conforming types will gain an `==` operator that
>>   ///   forwards to `===`.
>>   /// - Note: Types that require domain-specific `==`
>>   ///   implementations with different semantics (e.g. floating
>>   ///   point) should define a more-specific overload of `==`,
>>   ///   which will be used in contexts where the static type is
>>   ///   known to the compiler.
>>   /// - Note: Generic code should usually use `==` to compare
>>   ///   conforming instances; that will always dispatch to `===`
>>   ///   and will be unaffected by more specific overloads of
>>   ///   `==`.
>>   protocol Identifiable { // née Equatable name is negotiable
>> func ===(_: Self, _: aSelf) -> Bool
>>   }
>> 
>>   /// Default definition of `==` for Identifiable types.
>>   func ==(lhs: T, rhs: T) -> Bool {
>> return lhs === rhs
>>   }
>> 
>>   /// Conforming types have a default total ordering.
>>   ///
>>   /// If `a` and `b` are of type `Self`, `a <=> b` means that
>>   /// `a` and `b` are interchangeable in most code.  A conforming
>>   /// type can document that specific observable characteristics
>>   /// (such as the `capacity` of an `Array`) are inessential and
>>   /// thus not to be considered as part of the interchangeability
>>   /// guarantee.
>>   ///
>>   /// - Requires: `<=>` induces a total ordering over
>>   ///   instances.
>>   /// - 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Xiaodi Wu via swift-evolution
On Fri, Jul 22, 2016 at 9:09 PM, Jaden Geller 
wrote:

> 1. NaN != NaN and +0 == -0 [what the traditional comparison operators are
> constrained to do]
> 2. NaN == NaN, +0 == -0, and the same number encoded different ways
> compare equal
> 3. NaN == NaN, +0 != -0, and the same number encoded different ways
> compare not equal
>
>
> Though it seems super confusing that a language have THREE ways to compare
> values, that does almost seem necessary here. Do we actually need an
> operator that performs #3? I understand that that is equality under total
> ordering, but couldn't users just write `(a <=> b) == .same` if they want
> that?
>

For floating point types, I think `===` shouldn't be #3. From a practical
standpoint, no one ever wants that definition unless they are ordering
things. Whereas you'd want #2 for things like `.index(of:)` and #1 for the
traditional comparison operators.


>
> On Jul 22, 2016, at 7:04 PM, Xiaodi Wu  wrote:
>
> On Fri, Jul 22, 2016 at 8:57 PM, Matthew Johnson 
> wrote:
>
>>
>> On Jul 22, 2016, at 8:54 PM, Xiaodi Wu via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> On Fri, Jul 22, 2016 at 8:52 PM, Jaden Geller via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>> "The totalOrder predicate will order these cases, and it also
>>> distinguishes between different representations of NaNs and between the
>>> same decimal floating point number encoded in different ways."
>>> - [Wikipedia](
>>> https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate
>>> )
>>>
>>> Sounds like `===` should not return `true` for zeros of different signs,
>>> then.
>>>
>>
>> Fair enough; the result of that will be, as Pyry noted above, that:
>>
>> ```
>> [-0.0, 1.0, .nan, 0.0].firstIndex(of: 0.0) //=> 3, not 0
>> ```
>>
>>
>> Maybe we need floating point specific implementations of some algorithms
>> to resolve this problem?
>>
>> It doesn’t seem like there is a way to provide the semantics required by
>> generic algorithms and still provide the expected behavior for floating
>> point values.
>>
>
> Well, what I'm trying to say is that generic algorithms such as
> `index(of:)` require only an equivalence relation. For floating point
> types, there are three ways to slice it:
>
> 1. NaN != NaN and +0 == -0 [what the traditional comparison operators are
> constrained to do]
> 2. NaN == NaN, +0 == -0, and the same number encoded different ways
> compare equal
> 3. NaN == NaN, +0 != -0, and the same number encoded different ways
> compare not equal
>
> Both #2 and #3 can fall out of valid equivalence relations; if `===`
> behaved like #2 for FloatingPoint types, then generic algorithms work just
> fine. If we insist on using a total ordering defined by `<=>` all the time,
> then we've got problems.
>
>
>
>>
>>
>> On Jul 22, 2016, at 6:48 PM, Dave Abrahams via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
>>>
>>> on Fri Jul 22 2016, Jaden Geller  wrote:
>>>
>>> For floating point, I'd hope that `a === b` if `(a <=> b) == .same`
>>> *but not iff*. This is to satisfy IEEE 754: "Comparisons shall
>>> ignore the sign of zero (so +0 = −0)".
>>>
>>>
>>> I don't see why both `(+0) === (-0)` and `(+0) <=> (-0)` can't return
>>> `true` and `.same`, respectively. This doesn't break the total
>>> ordering of values. `===` doesn't do raw memory comparison. They're
>>> "identical", so it ought to return `true`.
>>>
>>>
>>> It ought to do whatever IEEE-754 specifies that its total ordering test
>>> does.  That is, IEEE-754 gets to decide whether the difference between
>>> +0 and -0 is “essential” to IEEE-754 floating point types, or not.
>>>
>>>
>>> On Jul 22, 2016, at 6:37 PM, Xiaodi Wu via swift-evolution
>>>  wrote:
>>>
>>> On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution
>>> >> >>
>>> wrote:
>>>
>>> on Fri Jul 22 2016, Daniel Duan >> > wrote:
>>>
>>> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution
>>> >> >>
>>> wrote:
>>>
>>>
>>> on Fri Jul 22 2016, Daniel Duan
>>> >> >
>>> 
>>> >> wrote:
>>>
>>>
>>> On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
>>> >> >
>>> 
>>> >> wrote:
>>>
>>>
>>> on Thu Jul 21 2016, Duan
>>>
>>>
>>> >> 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Xiaodi Wu via swift-evolution
On Fri, Jul 22, 2016 at 9:08 PM, Matthew Johnson 
wrote:

>
> On Jul 22, 2016, at 9:04 PM, Xiaodi Wu  wrote:
>
> On Fri, Jul 22, 2016 at 8:57 PM, Matthew Johnson 
> wrote:
>
>>
>> On Jul 22, 2016, at 8:54 PM, Xiaodi Wu via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> On Fri, Jul 22, 2016 at 8:52 PM, Jaden Geller via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>> "The totalOrder predicate will order these cases, and it also
>>> distinguishes between different representations of NaNs and between the
>>> same decimal floating point number encoded in different ways."
>>> - [Wikipedia](
>>> https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate
>>> )
>>>
>>> Sounds like `===` should not return `true` for zeros of different signs,
>>> then.
>>>
>>
>> Fair enough; the result of that will be, as Pyry noted above, that:
>>
>> ```
>> [-0.0, 1.0, .nan, 0.0].firstIndex(of: 0.0) //=> 3, not 0
>> ```
>>
>>
>> Maybe we need floating point specific implementations of some algorithms
>> to resolve this problem?
>>
>> It doesn’t seem like there is a way to provide the semantics required by
>> generic algorithms and still provide the expected behavior for floating
>> point values.
>>
>
> Well, what I'm trying to say is that generic algorithms such as
> `index(of:)` require only an equivalence relation. For floating point
> types, there are three ways to slice it:
>
> 1. NaN != NaN and +0 == -0 [what the traditional comparison operators are
> constrained to do]
> 2. NaN == NaN, +0 == -0, and the same number encoded different ways
> compare equal
> 3. NaN == NaN, +0 != -0, and the same number encoded different ways
> compare not equal
>
> Both #2 and #3 can fall out of valid equivalence relations; if `===`
> behaved like #2 for FloatingPoint types, then generic algorithms work just
> fine. If we insist on using a total ordering defined by `<=>` all the time,
> then we've got problems.
>
>
> And if we don’t then we’re back to 3 different concepts of equality.
> There is definitely a tradeoff no matter what we choose.
>

If some types have three concepts of equality, each with their particular
use, why must we eliminate one of them?


> On Jul 22, 2016, at 6:48 PM, Dave Abrahams via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
>>>
>>> on Fri Jul 22 2016, Jaden Geller  wrote:
>>>
>>> For floating point, I'd hope that `a === b` if `(a <=> b) == .same`
>>> *but not iff*. This is to satisfy IEEE 754: "Comparisons shall
>>> ignore the sign of zero (so +0 = −0)".
>>>
>>>
>>> I don't see why both `(+0) === (-0)` and `(+0) <=> (-0)` can't return
>>> `true` and `.same`, respectively. This doesn't break the total
>>> ordering of values. `===` doesn't do raw memory comparison. They're
>>> "identical", so it ought to return `true`.
>>>
>>>
>>> It ought to do whatever IEEE-754 specifies that its total ordering test
>>> does.  That is, IEEE-754 gets to decide whether the difference between
>>> +0 and -0 is “essential” to IEEE-754 floating point types, or not.
>>>
>>>
>>> On Jul 22, 2016, at 6:37 PM, Xiaodi Wu via swift-evolution
>>>  wrote:
>>>
>>> On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution
>>> >> >>
>>> wrote:
>>>
>>> on Fri Jul 22 2016, Daniel Duan >> > wrote:
>>>
>>> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution
>>> >> >>
>>> wrote:
>>>
>>>
>>> on Fri Jul 22 2016, Daniel Duan
>>> >> >
>>> 
>>> >> wrote:
>>>
>>>
>>> On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
>>> >> >
>>> 
>>> >> wrote:
>>>
>>>
>>> on Thu Jul 21 2016, Duan
>>>
>>>
>>> >> >
>>> 
>>> >>
>>> 
>>> >
>>> 
>>> 
>>> wrote:
>>>
>>> Great proposal. I want to second that areSame may mislead user to
>>> think this is about identity.
>>>
>>> I like areEquivalent() 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Jaden Geller via swift-evolution
> 1. NaN != NaN and +0 == -0 [what the traditional comparison operators are 
> constrained to do]
> 2. NaN == NaN, +0 == -0, and the same number encoded different ways compare 
> equal
> 3. NaN == NaN, +0 != -0, and the same number encoded different ways compare 
> not equal

Though it seems super confusing that a language have THREE ways to compare 
values, that does almost seem necessary here. Do we actually need an operator 
that performs #3? I understand that that is equality under total ordering, but 
couldn't users just write `(a <=> b) == .same` if they want that?

> On Jul 22, 2016, at 7:04 PM, Xiaodi Wu  wrote:
> 
> On Fri, Jul 22, 2016 at 8:57 PM, Matthew Johnson  > wrote:
> 
>> On Jul 22, 2016, at 8:54 PM, Xiaodi Wu via swift-evolution 
>> > wrote:
>> 
>> On Fri, Jul 22, 2016 at 8:52 PM, Jaden Geller via swift-evolution 
>> > wrote:
>> "The totalOrder predicate will order these cases, and it also distinguishes 
>> between different representations of NaNs and between the same decimal 
>> floating point number encoded in different ways."
>> - 
>> [Wikipedia](https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate
>>  
>> )
>> 
>> Sounds like `===` should not return `true` for zeros of different signs, 
>> then.
>> 
>> Fair enough; the result of that will be, as Pyry noted above, that:
>> 
>> ```
>> [-0.0, 1.0, .nan, 0.0].firstIndex(of: 0.0) //=> 3, not 0
>> ```
> 
> Maybe we need floating point specific implementations of some algorithms to 
> resolve this problem?
> 
> It doesn’t seem like there is a way to provide the semantics required by 
> generic algorithms and still provide the expected behavior for floating point 
> values.  
> 
> Well, what I'm trying to say is that generic algorithms such as `index(of:)` 
> require only an equivalence relation. For floating point types, there are 
> three ways to slice it:
> 
> 1. NaN != NaN and +0 == -0 [what the traditional comparison operators are 
> constrained to do]
> 2. NaN == NaN, +0 == -0, and the same number encoded different ways compare 
> equal
> 3. NaN == NaN, +0 != -0, and the same number encoded different ways compare 
> not equal
> 
> Both #2 and #3 can fall out of valid equivalence relations; if `===` behaved 
> like #2 for FloatingPoint types, then generic algorithms work just fine. If 
> we insist on using a total ordering defined by `<=>` all the time, then we've 
> got problems.
> 
>  
> 
>> 
>>> On Jul 22, 2016, at 6:48 PM, Dave Abrahams via swift-evolution 
>>> > wrote:
>>> 
>>> 
>>> on Fri Jul 22 2016, Jaden Geller >> > wrote:
>>> 
> For floating point, I'd hope that `a === b` if `(a <=> b) == .same`
> *but not iff*. This is to satisfy IEEE 754: "Comparisons shall
> ignore the sign of zero (so +0 = −0)".
 
 I don't see why both `(+0) === (-0)` and `(+0) <=> (-0)` can't return
 `true` and `.same`, respectively. This doesn't break the total
 ordering of values. `===` doesn't do raw memory comparison. They're
 "identical", so it ought to return `true`.
>>> 
>>> It ought to do whatever IEEE-754 specifies that its total ordering test
>>> does.  That is, IEEE-754 gets to decide whether the difference between
>>> +0 and -0 is “essential” to IEEE-754 floating point types, or not.
>>> 
 
> On Jul 22, 2016, at 6:37 PM, Xiaodi Wu via swift-evolution
> > wrote:
> 
> On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution
> 
> >>
> wrote:
> 
> on Fri Jul 22 2016, Daniel Duan  > wrote:
> 
>>> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution
>>> 
>>> >>
>>> wrote:
>>> 
>>> 
>>> on Fri Jul 22 2016, Daniel Duan
>>> 
>>> >
>>> 
>>> >> wrote:
>>> 
>> 
> On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
> 
> >

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Matthew Johnson via swift-evolution

> On Jul 22, 2016, at 9:04 PM, Xiaodi Wu  wrote:
> 
> On Fri, Jul 22, 2016 at 8:57 PM, Matthew Johnson  > wrote:
> 
>> On Jul 22, 2016, at 8:54 PM, Xiaodi Wu via swift-evolution 
>> > wrote:
>> 
>> On Fri, Jul 22, 2016 at 8:52 PM, Jaden Geller via swift-evolution 
>> > wrote:
>> "The totalOrder predicate will order these cases, and it also distinguishes 
>> between different representations of NaNs and between the same decimal 
>> floating point number encoded in different ways."
>> - 
>> [Wikipedia](https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate
>>  
>> )
>> 
>> Sounds like `===` should not return `true` for zeros of different signs, 
>> then.
>> 
>> Fair enough; the result of that will be, as Pyry noted above, that:
>> 
>> ```
>> [-0.0, 1.0, .nan, 0.0].firstIndex(of: 0.0) //=> 3, not 0
>> ```
> 
> Maybe we need floating point specific implementations of some algorithms to 
> resolve this problem?
> 
> It doesn’t seem like there is a way to provide the semantics required by 
> generic algorithms and still provide the expected behavior for floating point 
> values.  
> 
> Well, what I'm trying to say is that generic algorithms such as `index(of:)` 
> require only an equivalence relation. For floating point types, there are 
> three ways to slice it:
> 
> 1. NaN != NaN and +0 == -0 [what the traditional comparison operators are 
> constrained to do]
> 2. NaN == NaN, +0 == -0, and the same number encoded different ways compare 
> equal
> 3. NaN == NaN, +0 != -0, and the same number encoded different ways compare 
> not equal
> 
> Both #2 and #3 can fall out of valid equivalence relations; if `===` behaved 
> like #2 for FloatingPoint types, then generic algorithms work just fine. If 
> we insist on using a total ordering defined by `<=>` all the time, then we've 
> got problems.

And if we don’t then we’re back to 3 different concepts of equality.  There is 
definitely a tradeoff no matter what we choose.

> 
>  
> 
>> 
>>> On Jul 22, 2016, at 6:48 PM, Dave Abrahams via swift-evolution 
>>> > wrote:
>>> 
>>> 
>>> on Fri Jul 22 2016, Jaden Geller >> > wrote:
>>> 
> For floating point, I'd hope that `a === b` if `(a <=> b) == .same`
> *but not iff*. This is to satisfy IEEE 754: "Comparisons shall
> ignore the sign of zero (so +0 = −0)".
 
 I don't see why both `(+0) === (-0)` and `(+0) <=> (-0)` can't return
 `true` and `.same`, respectively. This doesn't break the total
 ordering of values. `===` doesn't do raw memory comparison. They're
 "identical", so it ought to return `true`.
>>> 
>>> It ought to do whatever IEEE-754 specifies that its total ordering test
>>> does.  That is, IEEE-754 gets to decide whether the difference between
>>> +0 and -0 is “essential” to IEEE-754 floating point types, or not.
>>> 
 
> On Jul 22, 2016, at 6:37 PM, Xiaodi Wu via swift-evolution
> > wrote:
> 
> On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution
> 
> >>
> wrote:
> 
> on Fri Jul 22 2016, Daniel Duan  > wrote:
> 
>>> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution
>>> 
>>> >>
>>> wrote:
>>> 
>>> 
>>> on Fri Jul 22 2016, Daniel Duan
>>> 
>>> >
>>> 
>>> >> wrote:
>>> 
>> 
> On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
> 
> >
> 
>   wrote:
> 
> 
> on Thu Jul 21 2016, Duan
 
> 
> >
> 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Xiaodi Wu via swift-evolution
On Fri, Jul 22, 2016 at 8:57 PM, Matthew Johnson 
wrote:

>
> On Jul 22, 2016, at 8:54 PM, Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> On Fri, Jul 22, 2016 at 8:52 PM, Jaden Geller via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> "The totalOrder predicate will order these cases, and it also
>> distinguishes between different representations of NaNs and between the
>> same decimal floating point number encoded in different ways."
>> - [Wikipedia](
>> https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate
>> )
>>
>> Sounds like `===` should not return `true` for zeros of different signs,
>> then.
>>
>
> Fair enough; the result of that will be, as Pyry noted above, that:
>
> ```
> [-0.0, 1.0, .nan, 0.0].firstIndex(of: 0.0) //=> 3, not 0
> ```
>
>
> Maybe we need floating point specific implementations of some algorithms
> to resolve this problem?
>
> It doesn’t seem like there is a way to provide the semantics required by
> generic algorithms and still provide the expected behavior for floating
> point values.
>

Well, what I'm trying to say is that generic algorithms such as
`index(of:)` require only an equivalence relation. For floating point
types, there are three ways to slice it:

1. NaN != NaN and +0 == -0 [what the traditional comparison operators are
constrained to do]
2. NaN == NaN, +0 == -0, and the same number encoded different ways compare
equal
3. NaN == NaN, +0 != -0, and the same number encoded different ways compare
not equal

Both #2 and #3 can fall out of valid equivalence relations; if `===`
behaved like #2 for FloatingPoint types, then generic algorithms work just
fine. If we insist on using a total ordering defined by `<=>` all the time,
then we've got problems.



>
>
> On Jul 22, 2016, at 6:48 PM, Dave Abrahams via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>
>> on Fri Jul 22 2016, Jaden Geller  wrote:
>>
>> For floating point, I'd hope that `a === b` if `(a <=> b) == .same`
>> *but not iff*. This is to satisfy IEEE 754: "Comparisons shall
>> ignore the sign of zero (so +0 = −0)".
>>
>>
>> I don't see why both `(+0) === (-0)` and `(+0) <=> (-0)` can't return
>> `true` and `.same`, respectively. This doesn't break the total
>> ordering of values. `===` doesn't do raw memory comparison. They're
>> "identical", so it ought to return `true`.
>>
>>
>> It ought to do whatever IEEE-754 specifies that its total ordering test
>> does.  That is, IEEE-754 gets to decide whether the difference between
>> +0 and -0 is “essential” to IEEE-754 floating point types, or not.
>>
>>
>> On Jul 22, 2016, at 6:37 PM, Xiaodi Wu via swift-evolution
>>  wrote:
>>
>> On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution
>> > >>
>> wrote:
>>
>> on Fri Jul 22 2016, Daniel Duan > > wrote:
>>
>> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution
>> > >>
>> wrote:
>>
>>
>> on Fri Jul 22 2016, Daniel Duan
>> > >
>> 
>> > wrote:
>>
>>
>> On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
>> > >
>> 
>> > wrote:
>>
>>
>> on Thu Jul 21 2016, Duan
>>
>>
>> > >
>> 
>> >>
>> 
>> >
>> 
>> 
>> wrote:
>>
>> Great proposal. I want to second that areSame may mislead user to
>> think this is about identity.
>>
>> I like areEquivalent() but there may be better names.
>>
>>
>> It really *is* about identity as I posted in a previous message.  But
>> that doesn't change the fact that areEquivalent might be a better name.
>> It's one of the things we considered; it just seemed long for no real
>> benefit.
>>
>>
>> If the addresses of the arguments aren’t being used, then we don’t
>> consider
>> them part of their *identity*. I can follow this logic. My fear is most
>> users
>> won’t make this leap on their own and get the same initial impression as
>> I did.
>> It's 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Jaden Geller via swift-evolution
> If `===` is the new `areSame`, and `Hashable` is based on `===`, wouldn't 
> that mean that objects could only be hashed (and thus, be looked up in 
> Dictionary and Set) by identity? So, for instance, code like this:
> 
>   var set = Set()
>   
>   set.insert("test")
>   set.insert("test")
>   
>   print(set.count)
> 
> Would print "2"? Or worse, might print "1" or "2" depending on the details of 
> how Swift generates literals and Foundation implements short strings?
> 
> Am I the only one who thinks that's a problem?

I was under the impression that the identity of an `NSObject` would use the 
existing `isEqual:` method. That is, identity doesn't necessarily mean 
reference identity anymore.

> On Jul 22, 2016, at 7:00 PM, Brent Royal-Gordon via swift-evolution 
>  wrote:
> 
>> On Jul 22, 2016, at 4:55 PM, Daniel Duan via swift-evolution 
>>  wrote:
>> 
>>> Well, it's still a very real question whether we ought to have the
>>> additional API surface implied by areSame, or wether we should collapse
>>> it with ===.
>>> 
>> 
>> To spell this out (because I had to think about it for a second): === will 
>> be derived from
>> <=>, but also becomes default implementation for ==, which remains open for 
>> customization.
>> 
>> I like this idea. If we keep === as a separate thing, now users have 3 
>> “opportunities” to define
>> equality. The must be few, if any, use cases for this.
>> 
>> Would love to see if anyone on the list can give us an example. Otherwise we 
>> should make
>> areSame === again™!
> 
> If `===` is the new `areSame`, and `Hashable` is based on `===`, wouldn't 
> that mean that objects could only be hashed (and thus, be looked up in 
> Dictionary and Set) by identity? So, for instance, code like this:
> 
>   var set = Set()
>   
>   set.insert("test")
>   set.insert("test")
>   
>   print(set.count)
> 
> Would print "2"? Or worse, might print "1" or "2" depending on the details of 
> how Swift generates literals and Foundation implements short strings?
> 
> Am I the only one who thinks that's a problem?
> 
> -- 
> Brent Royal-Gordon
> Architechies
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Jaden Geller via swift-evolution
> Fair enough; the result of that will be, as Pyry noted above, that:
> 
> ```
> [-0.0, 1.0, .nan, 0.0].firstIndex(of: 0.0) //=> 3, not 0
> ```

Well, ummm, that's unfortunate. This would be extremely surprising behavior, 
and I could easily see this causing bugs. Users would have to be very careful 
to write:
```
[-0.0, 1.0, .nan, 0.0].firstIndex(where: { $0 == 0 })
```

This might be a deal-breaker… unless:

> Maybe we need floating point specific implementations of some algorithms to 
> resolve this problem?

That seems like a reasonable workaround. I wish it weren't necessary though. 
Feels like we must have a flawed design. (Or IEEE does :P)

> On Jul 22, 2016, at 6:57 PM, Matthew Johnson  wrote:
> 
>> 
>> On Jul 22, 2016, at 8:54 PM, Xiaodi Wu via swift-evolution 
>> > wrote:
>> 
>> On Fri, Jul 22, 2016 at 8:52 PM, Jaden Geller via swift-evolution 
>> > wrote:
>> "The totalOrder predicate will order these cases, and it also distinguishes 
>> between different representations of NaNs and between the same decimal 
>> floating point number encoded in different ways."
>> - 
>> [Wikipedia](https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate
>>  
>> )
>> 
>> Sounds like `===` should not return `true` for zeros of different signs, 
>> then.
>> 
>> Fair enough; the result of that will be, as Pyry noted above, that:
>> 
>> ```
>> [-0.0, 1.0, .nan, 0.0].firstIndex(of: 0.0) //=> 3, not 0
>> ```
> 
> Maybe we need floating point specific implementations of some algorithms to 
> resolve this problem?
> 
> It doesn’t seem like there is a way to provide the semantics required by 
> generic algorithms and still provide the expected behavior for floating point 
> values.  
> 
>> 
>>> On Jul 22, 2016, at 6:48 PM, Dave Abrahams via swift-evolution 
>>> > wrote:
>>> 
>>> 
>>> on Fri Jul 22 2016, Jaden Geller >> > wrote:
>>> 
> For floating point, I'd hope that `a === b` if `(a <=> b) == .same`
> *but not iff*. This is to satisfy IEEE 754: "Comparisons shall
> ignore the sign of zero (so +0 = −0)".
 
 I don't see why both `(+0) === (-0)` and `(+0) <=> (-0)` can't return
 `true` and `.same`, respectively. This doesn't break the total
 ordering of values. `===` doesn't do raw memory comparison. They're
 "identical", so it ought to return `true`.
>>> 
>>> It ought to do whatever IEEE-754 specifies that its total ordering test
>>> does.  That is, IEEE-754 gets to decide whether the difference between
>>> +0 and -0 is “essential” to IEEE-754 floating point types, or not.
>>> 
 
> On Jul 22, 2016, at 6:37 PM, Xiaodi Wu via swift-evolution
> > wrote:
> 
> On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution
> 
> >>
> wrote:
> 
> on Fri Jul 22 2016, Daniel Duan  > wrote:
> 
>>> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution
>>> 
>>> >>
>>> wrote:
>>> 
>>> 
>>> on Fri Jul 22 2016, Daniel Duan
>>> 
>>> >
>>> 
>>> >> wrote:
>>> 
>> 
> On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
> 
> >
> 
>   wrote:
> 
> 
> on Thu Jul 21 2016, Duan
 
> 
> >
> 
> >>
> 
> >
> 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Brent Royal-Gordon via swift-evolution
> On Jul 22, 2016, at 4:55 PM, Daniel Duan via swift-evolution 
>  wrote:
> 
>> Well, it's still a very real question whether we ought to have the
>> additional API surface implied by areSame, or wether we should collapse
>> it with ===.
>> 
> 
> To spell this out (because I had to think about it for a second): === will be 
> derived from
> <=>, but also becomes default implementation for ==, which remains open for 
> customization.
> 
> I like this idea. If we keep === as a separate thing, now users have 3 
> “opportunities” to define
> equality. The must be few, if any, use cases for this.
> 
> Would love to see if anyone on the list can give us an example. Otherwise we 
> should make
> areSame === again™!

If `===` is the new `areSame`, and `Hashable` is based on `===`, wouldn't that 
mean that objects could only be hashed (and thus, be looked up in Dictionary 
and Set) by identity? So, for instance, code like this:

var set = Set()

set.insert("test")
set.insert("test")

print(set.count)

Would print "2"? Or worse, might print "1" or "2" depending on the details of 
how Swift generates literals and Foundation implements short strings?

Am I the only one who thinks that's a problem?

-- 
Brent Royal-Gordon
Architechies

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


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Matthew Johnson via swift-evolution

> On Jul 22, 2016, at 8:54 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> On Fri, Jul 22, 2016 at 8:52 PM, Jaden Geller via swift-evolution 
> > wrote:
> "The totalOrder predicate will order these cases, and it also distinguishes 
> between different representations of NaNs and between the same decimal 
> floating point number encoded in different ways."
> - 
> [Wikipedia](https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate
>  )
> 
> Sounds like `===` should not return `true` for zeros of different signs, then.
> 
> Fair enough; the result of that will be, as Pyry noted above, that:
> 
> ```
> [-0.0, 1.0, .nan, 0.0].firstIndex(of: 0.0) //=> 3, not 0
> ```

Maybe we need floating point specific implementations of some algorithms to 
resolve this problem?

It doesn’t seem like there is a way to provide the semantics required by 
generic algorithms and still provide the expected behavior for floating point 
values.  

> 
>> On Jul 22, 2016, at 6:48 PM, Dave Abrahams via swift-evolution 
>> > wrote:
>> 
>> 
>> on Fri Jul 22 2016, Jaden Geller > > wrote:
>> 
 For floating point, I'd hope that `a === b` if `(a <=> b) == .same`
 *but not iff*. This is to satisfy IEEE 754: "Comparisons shall
 ignore the sign of zero (so +0 = −0)".
>>> 
>>> I don't see why both `(+0) === (-0)` and `(+0) <=> (-0)` can't return
>>> `true` and `.same`, respectively. This doesn't break the total
>>> ordering of values. `===` doesn't do raw memory comparison. They're
>>> "identical", so it ought to return `true`.
>> 
>> It ought to do whatever IEEE-754 specifies that its total ordering test
>> does.  That is, IEEE-754 gets to decide whether the difference between
>> +0 and -0 is “essential” to IEEE-754 floating point types, or not.
>> 
>>> 
 On Jul 22, 2016, at 6:37 PM, Xiaodi Wu via swift-evolution
 > wrote:
 
 On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution
 
 >>
 wrote:
 
 on Fri Jul 22 2016, Daniel Duan >>> > wrote:
 
>> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution
>> 
>> >>
>> wrote:
>> 
>> 
>> on Fri Jul 22 2016, Daniel Duan
>> 
>> >
>> 
>> > wrote:
>> 
> 
 On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
 
 >
 
 >> 
 
 >
 
 >>
 
 >
 
 
 wrote:
 
> Great proposal. I want to second that areSame may mislead user to
> think this is about identity.
> 
> I like areEquivalent() but there may be better names.
 
 It really *is* about identity as I posted in a previous message.  But
 that doesn't change the fact that areEquivalent might be a better name.
 It's one of the things we considered; it just seemed long for no real
 benefit.
 
>>> 
>>> If the addresses of the arguments aren’t being used, then we don’t 
>>> consider
>>> them part of their *identity*. I can follow this logic. My fear is most 
>>> users
>>> won’t make this leap on their own and get the same initial 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Xiaodi Wu via swift-evolution
On Fri, Jul 22, 2016 at 8:52 PM, Jaden Geller via swift-evolution <
swift-evolution@swift.org> wrote:

> "The totalOrder predicate will order these cases, and it also
> distinguishes between different representations of NaNs and between the
> same decimal floating point number encoded in different ways."
> - [Wikipedia](
> https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate
> )
>
> Sounds like `===` should not return `true` for zeros of different signs,
> then.
>

Fair enough; the result of that will be, as Pyry noted above, that:

```
[-0.0, 1.0, .nan, 0.0].firstIndex(of: 0.0) //=> 3, not 0
```

On Jul 22, 2016, at 6:48 PM, Dave Abrahams via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>
> on Fri Jul 22 2016, Jaden Geller  wrote:
>
> For floating point, I'd hope that `a === b` if `(a <=> b) == .same`
> *but not iff*. This is to satisfy IEEE 754: "Comparisons shall
> ignore the sign of zero (so +0 = −0)".
>
>
> I don't see why both `(+0) === (-0)` and `(+0) <=> (-0)` can't return
> `true` and `.same`, respectively. This doesn't break the total
> ordering of values. `===` doesn't do raw memory comparison. They're
> "identical", so it ought to return `true`.
>
>
> It ought to do whatever IEEE-754 specifies that its total ordering test
> does.  That is, IEEE-754 gets to decide whether the difference between
> +0 and -0 is “essential” to IEEE-754 floating point types, or not.
>
>
> On Jul 22, 2016, at 6:37 PM, Xiaodi Wu via swift-evolution
>  wrote:
>
> On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution
>  >>
> wrote:
>
> on Fri Jul 22 2016, Daniel Duan  > wrote:
>
> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution
>  >>
> wrote:
>
>
> on Fri Jul 22 2016, Daniel Duan
>  >
> 
>  wrote:
>
>
> On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
>  >
> 
>  wrote:
>
>
> on Thu Jul 21 2016, Duan
>
>
>  >
> 
> >>
> 
> >
> 
> 
> wrote:
>
> Great proposal. I want to second that areSame may mislead user to
> think this is about identity.
>
> I like areEquivalent() but there may be better names.
>
>
> It really *is* about identity as I posted in a previous message.  But
> that doesn't change the fact that areEquivalent might be a better name.
> It's one of the things we considered; it just seemed long for no real
> benefit.
>
>
> If the addresses of the arguments aren’t being used, then we don’t consider
> them part of their *identity*. I can follow this logic. My fear is most
> users
> won’t make this leap on their own and get the same initial impression as I
> did.
> It's entirely possible this fear is unfounded. Some educated bikesheding
> wouldn't hurt here IMO :)
>
>
> Well, it's still a very real question whether we ought to have the
> additional API surface implied by areSame, or wether we should collapse
> it with ===.
>
>
> To spell this out (because I had to think about it for a second): === will
> be derived from
> <=>,
> but also becomes default implementation for ==, which remains open for
> customization.
>
>
> I was imagining roughly this (untested):
>
>  /// Two references are identical if they refer to the same
>  /// instance.
>  ///
>  /// - Note: Classes with a more-refined notion of “identical”
>  ///   should conform to `Identifiable` and implement `===`.
>  func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {
>ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
>  }
>
>  /// Supports testing that two values of `Self` are identical
>  ///
>  /// If `a` and `b` are of type `Self`, `a === b` means that
>  /// `a` and `b` are interchangeable in most code.  A conforming
>  /// type can document that specific observable characteristics
>  /// (such as the `capacity` of an `Array`) are inessential and
>  /// thus not to be considered as part of the interchangeability
>  /// guarantee.
>  ///
>  /// - 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Jaden Geller via swift-evolution
"The totalOrder predicate will order these cases, and it also distinguishes 
between different representations of NaNs and between the same decimal floating 
point number encoded in different ways."
- 
[Wikipedia](https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate)

Sounds like `===` should not return `true` for zeros of different signs, then.

> On Jul 22, 2016, at 6:48 PM, Dave Abrahams via swift-evolution 
>  wrote:
> 
> 
> on Fri Jul 22 2016, Jaden Geller  > wrote:
> 
>>> For floating point, I'd hope that `a === b` if `(a <=> b) == .same`
>>> *but not iff*. This is to satisfy IEEE 754: "Comparisons shall
>>> ignore the sign of zero (so +0 = −0)".
>> 
>> I don't see why both `(+0) === (-0)` and `(+0) <=> (-0)` can't return
>> `true` and `.same`, respectively. This doesn't break the total
>> ordering of values. `===` doesn't do raw memory comparison. They're
>> "identical", so it ought to return `true`.
> 
> It ought to do whatever IEEE-754 specifies that its total ordering test
> does.  That is, IEEE-754 gets to decide whether the difference between
> +0 and -0 is “essential” to IEEE-754 floating point types, or not.
> 
>> 
>>> On Jul 22, 2016, at 6:37 PM, Xiaodi Wu via swift-evolution
>>> > wrote:
>>> 
>>> On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution
>>> 
>>> >>
>>> wrote:
>>> 
>>> on Fri Jul 22 2016, Daniel Duan >> > wrote:
>>> 
> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution
> 
> >>
> wrote:
> 
> 
> on Fri Jul 22 2016, Daniel Duan
> 
> >
> 
>  wrote:
> 
 
>>> On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
>>> 
>>> >
>>> 
>>> >> wrote:
>>> 
>>> 
>>> on Thu Jul 21 2016, Duan
>> 
>>> 
>>> >
>>> 
>>> >>
>>> 
>>> >
>>> 
>>> 
>>> wrote:
>>> 
 Great proposal. I want to second that areSame may mislead user to
 think this is about identity.
 
 I like areEquivalent() but there may be better names.
>>> 
>>> It really *is* about identity as I posted in a previous message.  But
>>> that doesn't change the fact that areEquivalent might be a better name.
>>> It's one of the things we considered; it just seemed long for no real
>>> benefit.
>>> 
>> 
>> If the addresses of the arguments aren’t being used, then we don’t 
>> consider
>> them part of their *identity*. I can follow this logic. My fear is most 
>> users
>> won’t make this leap on their own and get the same initial impression as 
>> I did.
>> It's entirely possible this fear is unfounded. Some educated bikesheding
>> wouldn't hurt here IMO :)
> 
> Well, it's still a very real question whether we ought to have the
> additional API surface implied by areSame, or wether we should collapse
> it with ===.
> 
 
 To spell this out (because I had to think about it for a second): === will 
 be derived from
 <=>,
 but also becomes default implementation for ==, which remains open for
 customization.
>>> 
>>> I was imagining roughly this (untested):
>>> 
>>>  /// Two references are identical if they refer to the same
>>>  /// instance.
>>>  ///
>>>  /// - Note: Classes with a more-refined notion of “identical”
>>>  ///   should conform to `Identifiable` and implement `===`.
>>>  func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {
>>> 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Xiaodi Wu via swift-evolution
On Fri, Jul 22, 2016 at 8:46 PM, Matthew Johnson 
wrote:

>
> On Jul 22, 2016, at 8:43 PM, Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> On Fri, Jul 22, 2016 at 8:42 PM, Jaden Geller 
> wrote:
>
>> For floating point, I'd hope that `a === b` if `(a <=> b) == .same` *but
>> not iff*. This is to satisfy IEEE 754: "Comparisons shall ignore the sign
>> of zero (so +0 = −0)".
>>
>>
>> I don't see why both `(+0) === (-0)` and `(+0) <=> (-0)` can't return
>> `true` and `.same`, respectively.
>>
>
> IEEE 754 also demands that the total ordering place -0 below +0.
>
>
> Is this the proposed total ordering for floats in Swift (sorry, I haven’t
> followed the details of that)?
>

Yes, to the extent I understood the proposal.


> If so then it appears they must have separate identity and thus `===`
> would consider the sign value.  You would need to use `==` if you want IEEE
> 754 domain specific comparison.
>

That is one answer. It leads to Pyry's surprising result above though.


>
>
>
>> This doesn't break the total ordering of values. `===` doesn't do raw
>> memory comparison. They're "identical", so it ought to return `true`.
>>
>>
>> On Jul 22, 2016, at 6:37 PM, Xiaodi Wu via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>>
>>> on Fri Jul 22 2016, Daniel Duan >> > wrote:
>>>
>>> >> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>> >>
>>> >>
>>> >> on Fri Jul 22 2016, Daniel Duan > swift-evolution@swift.org>> wrote:
>>> >>
>>> >
>>>  On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
>>>  >
>>> wrote:
>>> 
>>> 
>>>  on Thu Jul 21 2016, Duan
>>> >>>
>>>  
>>>  >> >>>
>>>  wrote:
>>> 
>>> > Great proposal. I want to second that areSame may mislead user to
>>> > think this is about identity.
>>> >
>>> > I like areEquivalent() but there may be better names.
>>> 
>>>  It really *is* about identity as I posted in a previous message.
>>> But
>>>  that doesn't change the fact that areEquivalent might be a better
>>> name.
>>>  It's one of the things we considered; it just seemed long for no
>>> real
>>>  benefit.
>>> 
>>> >>>
>>> >>> If the addresses of the arguments aren’t being used, then we don’t
>>> consider
>>> >>> them part of their *identity*. I can follow this logic. My fear is
>>> most users
>>> >>> won’t make this leap on their own and get the same initial
>>> impression as I did.
>>> >>> It's entirely possible this fear is unfounded. Some educated
>>> bikesheding
>>> >>> wouldn't hurt here IMO :)
>>> >>
>>> >> Well, it's still a very real question whether we ought to have the
>>> >> additional API surface implied by areSame, or wether we should
>>> collapse
>>> >> it with ===.
>>> >>
>>> >
>>> > To spell this out (because I had to think about it for a second): ===
>>> will be derived from
>>> > <=>,
>>> > but also becomes default implementation for ==, which remains open for
>>> > customization.
>>>
>>> I was imagining roughly this (untested):
>>>
>>>   /// Two references are identical if they refer to the same
>>>   /// instance.
>>>   ///
>>>   /// - Note: Classes with a more-refined notion of “identical”
>>>   ///   should conform to `Identifiable` and implement `===`.
>>>   func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {
>>> ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
>>>   }
>>>
>>>   /// Supports testing that two values of `Self` are identical
>>>   ///
>>>   /// If `a` and `b` are of type `Self`, `a === b` means that
>>>   /// `a` and `b` are interchangeable in most code.  A conforming
>>>   /// type can document that specific observable characteristics
>>>   /// (such as the `capacity` of an `Array`) are inessential and
>>>   /// thus not to be considered as part of the interchangeability
>>>   /// guarantee.
>>>   ///
>>>   /// - Requires: `===` induces an equivalence relation over
>>>   ///   instances.
>>>   /// - Note: conforming types will gain an `==` operator that
>>>   ///   forwards to `===`.
>>>   /// - Note: Types that require domain-specific `==`
>>>   ///   implementations with different semantics (e.g. floating
>>>   ///   point) should define a more-specific overload of `==`,
>>>   ///   which will be used in contexts where the static type is
>>>   ///   known to the compiler.
>>>   /// - Note: Generic code should usually use `==` to compare
>>>   ///   conforming instances; that will always dispatch to `===`
>>>   ///   and will be unaffected by more specific overloads of
>>>   ///   `==`.
>>>  

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Dave Abrahams via swift-evolution

on Fri Jul 22 2016, Jaden Geller  wrote:

>> For floating point, I'd hope that `a === b` if `(a <=> b) == .same`
>> *but not iff*. This is to satisfy IEEE 754: "Comparisons shall
>> ignore the sign of zero (so +0 = −0)".
>
> I don't see why both `(+0) === (-0)` and `(+0) <=> (-0)` can't return
> `true` and `.same`, respectively. This doesn't break the total
> ordering of values. `===` doesn't do raw memory comparison. They're
> "identical", so it ought to return `true`.

It ought to do whatever IEEE-754 specifies that its total ordering test
does.  That is, IEEE-754 gets to decide whether the difference between
+0 and -0 is “essential” to IEEE-754 floating point types, or not.

>
>> On Jul 22, 2016, at 6:37 PM, Xiaodi Wu via swift-evolution
>>  wrote:
>> 
>> On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution
>> > >
>> wrote:
>> 
>> on Fri Jul 22 2016, Daniel Duan  wrote:
>> 
>> >> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution
>> >> > >> >
>> >> wrote:
>> >>
>> >>
>> >> on Fri Jul 22 2016, Daniel Duan
>> >> > >> 
>> >> > >> >>
>> >> wrote:
>> >>
>> >
>>  On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
>>  >  
>>  >  >>
>>  wrote:
>> 
>> 
>>  on Thu Jul 21 2016, Duan
>> >>>
>>  >  
>>  >  >
>>  >  
>>  >  >  wrote:
>> 
>> > Great proposal. I want to second that areSame may mislead user to
>> > think this is about identity.
>> >
>> > I like areEquivalent() but there may be better names.
>> 
>>  It really *is* about identity as I posted in a previous message.  But
>>  that doesn't change the fact that areEquivalent might be a better name.
>>  It's one of the things we considered; it just seemed long for no real
>>  benefit.
>> 
>> >>>
>> >>> If the addresses of the arguments aren’t being used, then we don’t 
>> >>> consider
>> >>> them part of their *identity*. I can follow this logic. My fear is most 
>> >>> users
>> >>> won’t make this leap on their own and get the same initial impression as 
>> >>> I did.
>> >>> It's entirely possible this fear is unfounded. Some educated bikesheding
>> >>> wouldn't hurt here IMO :)
>> >>
>> >> Well, it's still a very real question whether we ought to have the
>> >> additional API surface implied by areSame, or wether we should collapse
>> >> it with ===.
>> >>
>> >
>> > To spell this out (because I had to think about it for a second): === will 
>> > be derived from
>> > <=>,
>> > but also becomes default implementation for ==, which remains open for
>> > customization.
>> 
>> I was imagining roughly this (untested):
>> 
>>   /// Two references are identical if they refer to the same
>>   /// instance.
>>   ///
>>   /// - Note: Classes with a more-refined notion of “identical”
>>   ///   should conform to `Identifiable` and implement `===`.
>>   func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {
>> ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
>>   }
>> 
>>   /// Supports testing that two values of `Self` are identical
>>   ///
>>   /// If `a` and `b` are of type `Self`, `a === b` means that
>>   /// `a` and `b` are interchangeable in most code.  A conforming
>>   /// type can document that specific observable characteristics
>>   /// (such as the `capacity` of an `Array`) are inessential and
>>   /// thus not to be considered as part of the interchangeability
>>   /// guarantee.
>>   ///
>>   /// - Requires: `===` induces an equivalence relation over
>>   ///   instances.
>>   /// - Note: conforming types will gain an `==` operator that
>>   ///   forwards to `===`.
>>   /// - Note: Types that require domain-specific `==`
>>   ///   implementations with different semantics (e.g. floating
>>   ///   point) should define a more-specific overload of `==`,
>>   ///   which will be used in contexts where the static type is
>>   ///   known to the compiler.
>>   /// - Note: Generic code should usually use `==` to compare
>>   ///   conforming instances; that will always dispatch to `===`
>>   ///   and will be unaffected by more specific overloads of
>>   ///   `==`.
>>   protocol Identifiable { // née Equatable name is negotiable
>> func ===(_: Self, _: aSelf) -> Bool
>>   }
>> 
>>   /// Default 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Xiaodi Wu via swift-evolution
On Fri, Jul 22, 2016 at 8:45 PM, Dave Abrahams  wrote:

>
> on Fri Jul 22 2016, Xiaodi Wu  wrote:
>
> > On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution <
> > swift-evolution@swift.org> wrote:
> >
> >>
> >> on Fri Jul 22 2016, Daniel Duan  wrote:
> >>
> >> >> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution <
> >> swift-evolution@swift.org> wrote:
> >> >>
> >> >>
> >> >> on Fri Jul 22 2016, Daniel Duan > swift-evolution@swift.org>> wrote:
> >> >>
> >> >
> >>  On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
> >>  >
> wrote:
> >> 
> >> 
> >>  on Thu Jul 21 2016, Duan
> >> >>>
> >>  
> >>   >> >>>
> >>  wrote:
> >> 
> >> > Great proposal. I want to second that areSame may mislead user to
> >> > think this is about identity.
> >> >
> >> > I like areEquivalent() but there may be better names.
> >> 
> >>  It really *is* about identity as I posted in a previous message.
> But
> >>  that doesn't change the fact that areEquivalent might be a better
> >> name.
> >>  It's one of the things we considered; it just seemed long for no
> real
> >>  benefit.
> >> 
> >> >>>
> >> >>> If the addresses of the arguments aren’t being used, then we don’t
> >> consider
> >> >>> them part of their *identity*. I can follow this logic. My fear is
> >> most users
> >> >>> won’t make this leap on their own and get the same initial
> impression
> >> as I did.
> >> >>> It's entirely possible this fear is unfounded. Some educated
> >> bikesheding
> >> >>> wouldn't hurt here IMO :)
> >> >>
> >> >> Well, it's still a very real question whether we ought to have the
> >> >> additional API surface implied by areSame, or wether we should
> collapse
> >> >> it with ===.
> >> >>
> >> >
> >> > To spell this out (because I had to think about it for a second): ===
> >> will be derived from
> >> > <=>,
> >> > but also becomes default implementation for ==, which remains open for
> >> > customization.
> >>
> >> I was imagining roughly this (untested):
> >>
> >>   /// Two references are identical if they refer to the same
> >>   /// instance.
> >>   ///
> >>   /// - Note: Classes with a more-refined notion of “identical”
> >>   ///   should conform to `Identifiable` and implement `===`.
> >>   func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {
> >> ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
> >>   }
> >>
> >>   /// Supports testing that two values of `Self` are identical
> >>   ///
> >>   /// If `a` and `b` are of type `Self`, `a === b` means that
> >>   /// `a` and `b` are interchangeable in most code.  A conforming
> >>   /// type can document that specific observable characteristics
> >>   /// (such as the `capacity` of an `Array`) are inessential and
> >>   /// thus not to be considered as part of the interchangeability
> >>   /// guarantee.
> >>   ///
> >>   /// - Requires: `===` induces an equivalence relation over
> >>   ///   instances.
> >>   /// - Note: conforming types will gain an `==` operator that
> >>   ///   forwards to `===`.
> >>   /// - Note: Types that require domain-specific `==`
> >>   ///   implementations with different semantics (e.g. floating
> >>   ///   point) should define a more-specific overload of `==`,
> >>   ///   which will be used in contexts where the static type is
> >>   ///   known to the compiler.
> >>   /// - Note: Generic code should usually use `==` to compare
> >>   ///   conforming instances; that will always dispatch to `===`
> >>   ///   and will be unaffected by more specific overloads of
> >>   ///   `==`.
> >>   protocol Identifiable { // née Equatable name is negotiable
> >> func ===(_: Self, _: aSelf) -> Bool
> >>   }
> >>
> >>   /// Default definition of `==` for Identifiable types.
> >>   func ==(lhs: T, rhs: T) -> Bool {
> >> return lhs === rhs
> >>   }
> >>
> >>   /// Conforming types have a default total ordering.
> >>   ///
> >>   /// If `a` and `b` are of type `Self`, `a <=> b` means that
> >>   /// `a` and `b` are interchangeable in most code.  A conforming
> >>   /// type can document that specific observable characteristics
> >>   /// (such as the `capacity` of an `Array`) are inessential and
> >>   /// thus not to be considered as part of the interchangeability
> >>   /// guarantee.
> >>   ///
> >>   /// - Requires: `<=>` induces a total ordering over
> >>   ///   instances.
> >>   /// - Requires: the semantics of `<=>` are  consistent with
> >>   ///   those of `===`.  That is, `(a <=> b) == .equivalent`
> >>   ///   iff `a === b`.
> >>
> >
> > For floating point, I'd hope that `a === b` if `(a <=> b) == .same` *but
> > not iff*. This is to satisfy IEEE 754: "Comparisons shall ignore the sign
> > of zero (so +0 = −0)".
>

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Dave Abrahams via swift-evolution

on Fri Jul 22 2016, Xiaodi Wu  wrote:

> On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>>
>> on Fri Jul 22 2016, Daniel Duan  wrote:
>>
>> >> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution <
>> swift-evolution@swift.org> wrote:
>> >>
>> >>
>> >> on Fri Jul 22 2016, Daniel Duan  swift-evolution@swift.org>> wrote:
>> >>
>> >
>>  On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
>>  > wrote:
>> 
>> 
>>  on Thu Jul 21 2016, Duan
>> >>>
>>  
>>  > >>>
>>  wrote:
>> 
>> > Great proposal. I want to second that areSame may mislead user to
>> > think this is about identity.
>> >
>> > I like areEquivalent() but there may be better names.
>> 
>>  It really *is* about identity as I posted in a previous message.  But
>>  that doesn't change the fact that areEquivalent might be a better
>> name.
>>  It's one of the things we considered; it just seemed long for no real
>>  benefit.
>> 
>> >>>
>> >>> If the addresses of the arguments aren’t being used, then we don’t
>> consider
>> >>> them part of their *identity*. I can follow this logic. My fear is
>> most users
>> >>> won’t make this leap on their own and get the same initial impression
>> as I did.
>> >>> It's entirely possible this fear is unfounded. Some educated
>> bikesheding
>> >>> wouldn't hurt here IMO :)
>> >>
>> >> Well, it's still a very real question whether we ought to have the
>> >> additional API surface implied by areSame, or wether we should collapse
>> >> it with ===.
>> >>
>> >
>> > To spell this out (because I had to think about it for a second): ===
>> will be derived from
>> > <=>,
>> > but also becomes default implementation for ==, which remains open for
>> > customization.
>>
>> I was imagining roughly this (untested):
>>
>>   /// Two references are identical if they refer to the same
>>   /// instance.
>>   ///
>>   /// - Note: Classes with a more-refined notion of “identical”
>>   ///   should conform to `Identifiable` and implement `===`.
>>   func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {
>> ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
>>   }
>>
>>   /// Supports testing that two values of `Self` are identical
>>   ///
>>   /// If `a` and `b` are of type `Self`, `a === b` means that
>>   /// `a` and `b` are interchangeable in most code.  A conforming
>>   /// type can document that specific observable characteristics
>>   /// (such as the `capacity` of an `Array`) are inessential and
>>   /// thus not to be considered as part of the interchangeability
>>   /// guarantee.
>>   ///
>>   /// - Requires: `===` induces an equivalence relation over
>>   ///   instances.
>>   /// - Note: conforming types will gain an `==` operator that
>>   ///   forwards to `===`.
>>   /// - Note: Types that require domain-specific `==`
>>   ///   implementations with different semantics (e.g. floating
>>   ///   point) should define a more-specific overload of `==`,
>>   ///   which will be used in contexts where the static type is
>>   ///   known to the compiler.
>>   /// - Note: Generic code should usually use `==` to compare
>>   ///   conforming instances; that will always dispatch to `===`
>>   ///   and will be unaffected by more specific overloads of
>>   ///   `==`.
>>   protocol Identifiable { // née Equatable name is negotiable
>> func ===(_: Self, _: aSelf) -> Bool
>>   }
>>
>>   /// Default definition of `==` for Identifiable types.
>>   func ==(lhs: T, rhs: T) -> Bool {
>> return lhs === rhs
>>   }
>>
>>   /// Conforming types have a default total ordering.
>>   ///
>>   /// If `a` and `b` are of type `Self`, `a <=> b` means that
>>   /// `a` and `b` are interchangeable in most code.  A conforming
>>   /// type can document that specific observable characteristics
>>   /// (such as the `capacity` of an `Array`) are inessential and
>>   /// thus not to be considered as part of the interchangeability
>>   /// guarantee.
>>   ///
>>   /// - Requires: `<=>` induces a total ordering over
>>   ///   instances.
>>   /// - Requires: the semantics of `<=>` are  consistent with
>>   ///   those of `===`.  That is, `(a <=> b) == .equivalent`
>>   ///   iff `a === b`.
>>
>
> For floating point, I'd hope that `a === b` if `(a <=> b) == .same` *but
> not iff*. This is to satisfy IEEE 754: "Comparisons shall ignore the sign
> of zero (so +0 = −0)".

By “comparisons” they mean the traditional comparison operators, not all
possible comparisons you might want to do.

That single equal sign in their text corresponds to == in the world
being proposed, so that's fine.

>
>
>>   /// - Note: conforming types will gain `<`, `<=`, `>`, and `>=`
>>   ///   operators defined 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Matthew Johnson via swift-evolution

> On Jul 22, 2016, at 8:43 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> On Fri, Jul 22, 2016 at 8:42 PM, Jaden Geller  > wrote:
>> For floating point, I'd hope that `a === b` if `(a <=> b) == .same` *but not 
>> iff*. This is to satisfy IEEE 754: "Comparisons shall ignore the sign of 
>> zero (so +0 = −0)".
> 
> I don't see why both `(+0) === (-0)` and `(+0) <=> (-0)` can't return `true` 
> and `.same`, respectively.
> 
> IEEE 754 also demands that the total ordering place -0 below +0.

Is this the proposed total ordering for floats in Swift (sorry, I haven’t 
followed the details of that)?  If so then it appears they must have separate 
identity and thus `===` would consider the sign value.  You would need to use 
`==` if you want IEEE 754 domain specific comparison.

>  
> This doesn't break the total ordering of values. `===` doesn't do raw memory 
> comparison. They're "identical", so it ought to return `true`.
> 
> 
>> On Jul 22, 2016, at 6:37 PM, Xiaodi Wu via swift-evolution 
>> > wrote:
>> 
>> On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution 
>> > wrote:
>> 
>> on Fri Jul 22 2016, Daniel Duan > > wrote:
>> 
>> >> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution 
>> >> > wrote:
>> >>
>> >>
>> >> on Fri Jul 22 2016, Daniel Duan > >>  > >> >> wrote:
>> >>
>> >
>>  On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
>>   
>>  >> 
>>  wrote:
>> 
>> 
>>  on Thu Jul 21 2016, Duan
>> >>>
>>   
>>  >
>>   
>>  >  wrote:
>> 
>> > Great proposal. I want to second that areSame may mislead user to
>> > think this is about identity.
>> >
>> > I like areEquivalent() but there may be better names.
>> 
>>  It really *is* about identity as I posted in a previous message.  But
>>  that doesn't change the fact that areEquivalent might be a better name.
>>  It's one of the things we considered; it just seemed long for no real
>>  benefit.
>> 
>> >>>
>> >>> If the addresses of the arguments aren’t being used, then we don’t 
>> >>> consider
>> >>> them part of their *identity*. I can follow this logic. My fear is most 
>> >>> users
>> >>> won’t make this leap on their own and get the same initial impression as 
>> >>> I did.
>> >>> It's entirely possible this fear is unfounded. Some educated bikesheding
>> >>> wouldn't hurt here IMO :)
>> >>
>> >> Well, it's still a very real question whether we ought to have the
>> >> additional API surface implied by areSame, or wether we should collapse
>> >> it with ===.
>> >>
>> >
>> > To spell this out (because I had to think about it for a second): === will 
>> > be derived from
>> > <=>,
>> > but also becomes default implementation for ==, which remains open for
>> > customization.
>> 
>> I was imagining roughly this (untested):
>> 
>>   /// Two references are identical if they refer to the same
>>   /// instance.
>>   ///
>>   /// - Note: Classes with a more-refined notion of “identical”
>>   ///   should conform to `Identifiable` and implement `===`.
>>   func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {
>> ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
>>   }
>> 
>>   /// Supports testing that two values of `Self` are identical
>>   ///
>>   /// If `a` and `b` are of type `Self`, `a === b` means that
>>   /// `a` and `b` are interchangeable in most code.  A conforming
>>   /// type can document that specific observable characteristics
>>   /// (such as the `capacity` of an `Array`) are inessential and
>>   /// thus not to be considered as part of the interchangeability
>>   /// guarantee.
>>   ///
>>   /// - Requires: `===` induces an equivalence relation over
>>   ///   instances.
>>   /// - Note: conforming types will gain an `==` operator that
>>   ///   forwards to `===`.
>>   /// - Note: Types that require domain-specific `==`
>>   ///   implementations with different semantics (e.g. floating
>>   ///   point) should define a more-specific overload of `==`,
>>   ///   which will be used in contexts where the static type is
>>   ///   known to the compiler.
>>   /// - Note: Generic code should usually use `==` to 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Xiaodi Wu via swift-evolution
On Fri, Jul 22, 2016 at 8:44 PM, Matthew Johnson 
wrote:

>
> On Jul 22, 2016, at 8:37 PM, Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>>
>> on Fri Jul 22 2016, Daniel Duan > > wrote:
>>
>> >> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution <
>> swift-evolution@swift.org> wrote:
>> >>
>> >>
>> >> on Fri Jul 22 2016, Daniel Duan  swift-evolution@swift.org>> wrote:
>> >>
>> >
>>  On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
>>  >
>> wrote:
>> 
>> 
>>  on Thu Jul 21 2016, Duan
>> >>>
>>  
>>  > >>>
>>  wrote:
>> 
>> > Great proposal. I want to second that areSame may mislead user to
>> > think this is about identity.
>> >
>> > I like areEquivalent() but there may be better names.
>> 
>>  It really *is* about identity as I posted in a previous message.  But
>>  that doesn't change the fact that areEquivalent might be a better
>> name.
>>  It's one of the things we considered; it just seemed long for no real
>>  benefit.
>> 
>> >>>
>> >>> If the addresses of the arguments aren’t being used, then we don’t
>> consider
>> >>> them part of their *identity*. I can follow this logic. My fear is
>> most users
>> >>> won’t make this leap on their own and get the same initial impression
>> as I did.
>> >>> It's entirely possible this fear is unfounded. Some educated
>> bikesheding
>> >>> wouldn't hurt here IMO :)
>> >>
>> >> Well, it's still a very real question whether we ought to have the
>> >> additional API surface implied by areSame, or wether we should collapse
>> >> it with ===.
>> >>
>> >
>> > To spell this out (because I had to think about it for a second): ===
>> will be derived from
>> > <=>,
>> > but also becomes default implementation for ==, which remains open for
>> > customization.
>>
>> I was imagining roughly this (untested):
>>
>>   /// Two references are identical if they refer to the same
>>   /// instance.
>>   ///
>>   /// - Note: Classes with a more-refined notion of “identical”
>>   ///   should conform to `Identifiable` and implement `===`.
>>   func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {
>> ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
>>   }
>>
>>   /// Supports testing that two values of `Self` are identical
>>   ///
>>   /// If `a` and `b` are of type `Self`, `a === b` means that
>>   /// `a` and `b` are interchangeable in most code.  A conforming
>>   /// type can document that specific observable characteristics
>>   /// (such as the `capacity` of an `Array`) are inessential and
>>   /// thus not to be considered as part of the interchangeability
>>   /// guarantee.
>>   ///
>>   /// - Requires: `===` induces an equivalence relation over
>>   ///   instances.
>>   /// - Note: conforming types will gain an `==` operator that
>>   ///   forwards to `===`.
>>   /// - Note: Types that require domain-specific `==`
>>   ///   implementations with different semantics (e.g. floating
>>   ///   point) should define a more-specific overload of `==`,
>>   ///   which will be used in contexts where the static type is
>>   ///   known to the compiler.
>>   /// - Note: Generic code should usually use `==` to compare
>>   ///   conforming instances; that will always dispatch to `===`
>>   ///   and will be unaffected by more specific overloads of
>>   ///   `==`.
>>   protocol Identifiable { // née Equatable name is negotiable
>> func ===(_: Self, _: aSelf) -> Bool
>>   }
>>
>>   /// Default definition of `==` for Identifiable types.
>>   func ==(lhs: T, rhs: T) -> Bool {
>> return lhs === rhs
>>   }
>>
>>   /// Conforming types have a default total ordering.
>>   ///
>>   /// If `a` and `b` are of type `Self`, `a <=> b` means that
>>   /// `a` and `b` are interchangeable in most code.  A conforming
>>   /// type can document that specific observable characteristics
>>   /// (such as the `capacity` of an `Array`) are inessential and
>>   /// thus not to be considered as part of the interchangeability
>>   /// guarantee.
>>   ///
>>   /// - Requires: `<=>` induces a total ordering over
>>   ///   instances.
>>   /// - Requires: the semantics of `<=>` are  consistent with
>>   ///   those of `===`.  That is, `(a <=> b) == .equivalent`
>>   ///   iff `a === b`.
>>
>
> For floating point, I'd hope that `a === b` if `(a <=> b) == .same` *but
> not iff*. This is to satisfy IEEE 754: "Comparisons shall ignore the sign
> of zero (so +0 = −0)”.
>
>
> The point of this design is that `===` means identity and that `.same `
> also means identity.
>
> Since this is new territory I suppose 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Xiaodi Wu via swift-evolution
On Fri, Jul 22, 2016 at 8:42 PM, Jaden Geller 
wrote:

> For floating point, I'd hope that `a === b` if `(a <=> b) == .same` *but
> not iff*. This is to satisfy IEEE 754: "Comparisons shall ignore the sign
> of zero (so +0 = −0)".
>
>
> I don't see why both `(+0) === (-0)` and `(+0) <=> (-0)` can't return
> `true` and `.same`, respectively.
>

IEEE 754 also demands that the total ordering place -0 below +0.


> This doesn't break the total ordering of values. `===` doesn't do raw
> memory comparison. They're "identical", so it ought to return `true`.
>
>
> On Jul 22, 2016, at 6:37 PM, Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>>
>> on Fri Jul 22 2016, Daniel Duan > > wrote:
>>
>> >> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution <
>> swift-evolution@swift.org> wrote:
>> >>
>> >>
>> >> on Fri Jul 22 2016, Daniel Duan  swift-evolution@swift.org>> wrote:
>> >>
>> >
>>  On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
>>  >
>> wrote:
>> 
>> 
>>  on Thu Jul 21 2016, Duan
>> >>>
>>  
>>  > >>>
>>  wrote:
>> 
>> > Great proposal. I want to second that areSame may mislead user to
>> > think this is about identity.
>> >
>> > I like areEquivalent() but there may be better names.
>> 
>>  It really *is* about identity as I posted in a previous message.  But
>>  that doesn't change the fact that areEquivalent might be a better
>> name.
>>  It's one of the things we considered; it just seemed long for no real
>>  benefit.
>> 
>> >>>
>> >>> If the addresses of the arguments aren’t being used, then we don’t
>> consider
>> >>> them part of their *identity*. I can follow this logic. My fear is
>> most users
>> >>> won’t make this leap on their own and get the same initial impression
>> as I did.
>> >>> It's entirely possible this fear is unfounded. Some educated
>> bikesheding
>> >>> wouldn't hurt here IMO :)
>> >>
>> >> Well, it's still a very real question whether we ought to have the
>> >> additional API surface implied by areSame, or wether we should collapse
>> >> it with ===.
>> >>
>> >
>> > To spell this out (because I had to think about it for a second): ===
>> will be derived from
>> > <=>,
>> > but also becomes default implementation for ==, which remains open for
>> > customization.
>>
>> I was imagining roughly this (untested):
>>
>>   /// Two references are identical if they refer to the same
>>   /// instance.
>>   ///
>>   /// - Note: Classes with a more-refined notion of “identical”
>>   ///   should conform to `Identifiable` and implement `===`.
>>   func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {
>> ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
>>   }
>>
>>   /// Supports testing that two values of `Self` are identical
>>   ///
>>   /// If `a` and `b` are of type `Self`, `a === b` means that
>>   /// `a` and `b` are interchangeable in most code.  A conforming
>>   /// type can document that specific observable characteristics
>>   /// (such as the `capacity` of an `Array`) are inessential and
>>   /// thus not to be considered as part of the interchangeability
>>   /// guarantee.
>>   ///
>>   /// - Requires: `===` induces an equivalence relation over
>>   ///   instances.
>>   /// - Note: conforming types will gain an `==` operator that
>>   ///   forwards to `===`.
>>   /// - Note: Types that require domain-specific `==`
>>   ///   implementations with different semantics (e.g. floating
>>   ///   point) should define a more-specific overload of `==`,
>>   ///   which will be used in contexts where the static type is
>>   ///   known to the compiler.
>>   /// - Note: Generic code should usually use `==` to compare
>>   ///   conforming instances; that will always dispatch to `===`
>>   ///   and will be unaffected by more specific overloads of
>>   ///   `==`.
>>   protocol Identifiable { // née Equatable name is negotiable
>> func ===(_: Self, _: aSelf) -> Bool
>>   }
>>
>>   /// Default definition of `==` for Identifiable types.
>>   func ==(lhs: T, rhs: T) -> Bool {
>> return lhs === rhs
>>   }
>>
>>   /// Conforming types have a default total ordering.
>>   ///
>>   /// If `a` and `b` are of type `Self`, `a <=> b` means that
>>   /// `a` and `b` are interchangeable in most code.  A conforming
>>   /// type can document that specific observable characteristics
>>   /// (such as the `capacity` of an `Array`) are inessential and
>>   /// thus not to be considered as part of the interchangeability
>>   /// guarantee.
>>   ///
>>   /// - Requires: `<=>` induces a total ordering over

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Dave Abrahams via swift-evolution

on Fri Jul 22 2016, Jaden Geller  wrote:

> I really like this idea. I was initially opposed to changing the
> behavior of `===`, but I think I'm for it now. Though there have been
> quite a few situations where I specifically want reference identity,
> in these situations I would not override the `===` operator anyway;
> these objects were identified by their reference.
>
> I think this refinement of the proposal makes the semantics easier to
> reason about, and nicely repurposes the `===` operator instead of
> introducing a new 3rd notion of equality. If users explicitly want to
> compare references, it isn't difficult to create an
> `ObjectIdentifier`, and it probably leads to clearer code in cases
> where the object identity isn't defined by it's reference.
>
> Could types that conform to `Comparable` not get a default implementation of 
> `===`?

Yes they could.  In fact I meant to write it and left it out.  And the
docs should say don't provide your own definition of `===` for a
Comparable type unless its semantics match the default.

>> On Jul 22, 2016, at 6:20 PM, Dave Abrahams via swift-evolution 
>>  wrote:
>> 
>> 
>> on Fri Jul 22 2016, Daniel Duan  wrote:
>> 
 On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution 
  wrote:
 
 
 on Fri Jul 22 2016, Daniel Duan > wrote:
 
>>> 
>> On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
>> > wrote:
>> 
>> 
>> on Thu Jul 21 2016, Duan
> 
>> 
>> >>
>> wrote:
>> 
>>> Great proposal. I want to second that areSame may mislead user to
>>> think this is about identity.
>>> 
>>> I like areEquivalent() but there may be better names.
>> 
>> It really *is* about identity as I posted in a previous message.  But
>> that doesn't change the fact that areEquivalent might be a better name.
>> It's one of the things we considered; it just seemed long for no real
>> benefit.
>> 
> 
> If the addresses of the arguments aren’t being used, then we don’t 
> consider
> them part of their *identity*. I can follow this logic. My fear is most 
> users
> won’t make this leap on their own and get the same initial impression as 
> I did.
> It's entirely possible this fear is unfounded. Some educated bikesheding
> wouldn't hurt here IMO :)
 
 Well, it's still a very real question whether we ought to have the
 additional API surface implied by areSame, or wether we should collapse
 it with ===.
 
>>> 
>>> To spell this out (because I had to think about it for a second): === will 
>>> be derived from
>>> <=>, 
>>> but also becomes default implementation for ==, which remains open for
>>> customization.
>> 
>> I was imagining roughly this (untested):
>> 
>>  /// Two references are identical if they refer to the same
>>  /// instance.
>>  ///
>>  /// - Note: Classes with a more-refined notion of “identical” 
>>  ///   should conform to `Identifiable` and implement `===`.
>>  func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {
>>ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
>>  }
>> 
>>  /// Supports testing that two values of `Self` are identical
>>  ///
>>  /// If `a` and `b` are of type `Self`, `a === b` means that
>>  /// `a` and `b` are interchangeable in most code.  A conforming 
>>  /// type can document that specific observable characteristics
>>  /// (such as the `capacity` of an `Array`) are inessential and 
>>  /// thus not to be considered as part of the interchangeability 
>>  /// guarantee.
>>  ///
>>  /// - Requires: `===` induces an equivalence relation over
>>  ///   instances.
>>  /// - Note: conforming types will gain an `==` operator that 
>>  ///   forwards to `===`.  
>>  /// - Note: Types that require domain-specific `==` 
>>  ///   implementations with different semantics (e.g. floating 
>>  ///   point) should define a more-specific overload of `==`, 
>>  ///   which will be used in contexts where the static type is
>>  ///   known to the compiler.
>>  /// - Note: Generic code should usually use `==` to compare 
>>  ///   conforming instances; that will always dispatch to `===` 
>>  ///   and will be unaffected by more specific overloads of
>>  ///   `==`.
>>  protocol Identifiable { // née Equatable name is negotiable
>>func ===(_: Self, _: aSelf) -> Bool
>>  }
>> 
>>  /// Default definition of `==` for Identifiable types.
>>  func ==(lhs: T, rhs: T) -> Bool {
>>return lhs === rhs
>>  }
>> 
>>  /// Conforming types have a default total ordering.
>>  /// 
>>  /// If `a` and `b` are of type `Self`, `a <=> b` means that
>>  /// `a` and `b` are interchangeable in most 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Xiaodi Wu via swift-evolution
On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution <
swift-evolution@swift.org> wrote:

>
> on Fri Jul 22 2016, Daniel Duan  wrote:
>
> >> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution <
> swift-evolution@swift.org> wrote:
> >>
> >>
> >> on Fri Jul 22 2016, Daniel Duan > wrote:
> >>
> >
>  On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
>  > wrote:
> 
> 
>  on Thu Jul 21 2016, Duan
> >>>
>  
>   >>>
>  wrote:
> 
> > Great proposal. I want to second that areSame may mislead user to
> > think this is about identity.
> >
> > I like areEquivalent() but there may be better names.
> 
>  It really *is* about identity as I posted in a previous message.  But
>  that doesn't change the fact that areEquivalent might be a better
> name.
>  It's one of the things we considered; it just seemed long for no real
>  benefit.
> 
> >>>
> >>> If the addresses of the arguments aren’t being used, then we don’t
> consider
> >>> them part of their *identity*. I can follow this logic. My fear is
> most users
> >>> won’t make this leap on their own and get the same initial impression
> as I did.
> >>> It's entirely possible this fear is unfounded. Some educated
> bikesheding
> >>> wouldn't hurt here IMO :)
> >>
> >> Well, it's still a very real question whether we ought to have the
> >> additional API surface implied by areSame, or wether we should collapse
> >> it with ===.
> >>
> >
> > To spell this out (because I had to think about it for a second): ===
> will be derived from
> > <=>,
> > but also becomes default implementation for ==, which remains open for
> > customization.
>
> I was imagining roughly this (untested):
>
>   /// Two references are identical if they refer to the same
>   /// instance.
>   ///
>   /// - Note: Classes with a more-refined notion of “identical”
>   ///   should conform to `Identifiable` and implement `===`.
>   func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {
> ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
>   }
>
>   /// Supports testing that two values of `Self` are identical
>   ///
>   /// If `a` and `b` are of type `Self`, `a === b` means that
>   /// `a` and `b` are interchangeable in most code.  A conforming
>   /// type can document that specific observable characteristics
>   /// (such as the `capacity` of an `Array`) are inessential and
>   /// thus not to be considered as part of the interchangeability
>   /// guarantee.
>   ///
>   /// - Requires: `===` induces an equivalence relation over
>   ///   instances.
>   /// - Note: conforming types will gain an `==` operator that
>   ///   forwards to `===`.
>   /// - Note: Types that require domain-specific `==`
>   ///   implementations with different semantics (e.g. floating
>   ///   point) should define a more-specific overload of `==`,
>   ///   which will be used in contexts where the static type is
>   ///   known to the compiler.
>   /// - Note: Generic code should usually use `==` to compare
>   ///   conforming instances; that will always dispatch to `===`
>   ///   and will be unaffected by more specific overloads of
>   ///   `==`.
>   protocol Identifiable { // née Equatable name is negotiable
> func ===(_: Self, _: aSelf) -> Bool
>   }
>
>   /// Default definition of `==` for Identifiable types.
>   func ==(lhs: T, rhs: T) -> Bool {
> return lhs === rhs
>   }
>
>   /// Conforming types have a default total ordering.
>   ///
>   /// If `a` and `b` are of type `Self`, `a <=> b` means that
>   /// `a` and `b` are interchangeable in most code.  A conforming
>   /// type can document that specific observable characteristics
>   /// (such as the `capacity` of an `Array`) are inessential and
>   /// thus not to be considered as part of the interchangeability
>   /// guarantee.
>   ///
>   /// - Requires: `<=>` induces a total ordering over
>   ///   instances.
>   /// - Requires: the semantics of `<=>` are  consistent with
>   ///   those of `===`.  That is, `(a <=> b) == .equivalent`
>   ///   iff `a === b`.
>

For floating point, I'd hope that `a === b` if `(a <=> b) == .same` *but
not iff*. This is to satisfy IEEE 754: "Comparisons shall ignore the sign
of zero (so +0 = −0)".


>   /// - Note: conforming types will gain `<`, `<=`, `>`, and `>=`
>   ///   operators defined in terms of `<=>`.
>   /// - Note: Types that require domain-specific `<`, etc.
>   ///   implementations with different semantics (e.g. floating
>   ///   point) should define more-specific overloads of those
>   ///   operators, which will be used in contexts where the
>   ///   static type is known to the compiler.
>   /// - Note: Generic code can freely use `<=>` or the traditional

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Jaden Geller via swift-evolution
I really like this idea. I was initially opposed to changing the behavior of 
`===`, but I think I'm for it now. Though there have been quite a few 
situations where I specifically want reference identity, in these situations I 
would not override the `===` operator anyway; these objects were identified by 
their reference.

I think this refinement of the proposal makes the semantics easier to reason 
about, and nicely repurposes the `===` operator instead of introducing a new 
3rd notion of equality. If users explicitly want to compare references, it 
isn't difficult to create an `ObjectIdentifier`, and it probably leads to 
clearer code in cases where the object identity isn't defined by it's reference.

Could types that conform to `Comparable` not get a default implementation of 
`===`?

> On Jul 22, 2016, at 6:20 PM, Dave Abrahams via swift-evolution 
>  wrote:
> 
> 
> on Fri Jul 22 2016, Daniel Duan  wrote:
> 
>>> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution 
>>>  wrote:
>>> 
>>> 
>>> on Fri Jul 22 2016, Daniel Duan >> > wrote:
>>> 
>> 
> On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
> > wrote:
> 
> 
> on Thu Jul 21 2016, Duan
 
> 
> >>
> wrote:
> 
>> Great proposal. I want to second that areSame may mislead user to
>> think this is about identity.
>> 
>> I like areEquivalent() but there may be better names.
> 
> It really *is* about identity as I posted in a previous message.  But
> that doesn't change the fact that areEquivalent might be a better name.
> It's one of the things we considered; it just seemed long for no real
> benefit.
> 
 
 If the addresses of the arguments aren’t being used, then we don’t consider
 them part of their *identity*. I can follow this logic. My fear is most 
 users
 won’t make this leap on their own and get the same initial impression as I 
 did.
 It's entirely possible this fear is unfounded. Some educated bikesheding
 wouldn't hurt here IMO :)
>>> 
>>> Well, it's still a very real question whether we ought to have the
>>> additional API surface implied by areSame, or wether we should collapse
>>> it with ===.
>>> 
>> 
>> To spell this out (because I had to think about it for a second): === will 
>> be derived from
>> <=>, 
>> but also becomes default implementation for ==, which remains open for
>> customization.
> 
> I was imagining roughly this (untested):
> 
>  /// Two references are identical if they refer to the same
>  /// instance.
>  ///
>  /// - Note: Classes with a more-refined notion of “identical” 
>  ///   should conform to `Identifiable` and implement `===`.
>  func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {
>ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
>  }
> 
>  /// Supports testing that two values of `Self` are identical
>  ///
>  /// If `a` and `b` are of type `Self`, `a === b` means that
>  /// `a` and `b` are interchangeable in most code.  A conforming 
>  /// type can document that specific observable characteristics
>  /// (such as the `capacity` of an `Array`) are inessential and 
>  /// thus not to be considered as part of the interchangeability 
>  /// guarantee.
>  ///
>  /// - Requires: `===` induces an equivalence relation over
>  ///   instances.
>  /// - Note: conforming types will gain an `==` operator that 
>  ///   forwards to `===`.  
>  /// - Note: Types that require domain-specific `==` 
>  ///   implementations with different semantics (e.g. floating 
>  ///   point) should define a more-specific overload of `==`, 
>  ///   which will be used in contexts where the static type is
>  ///   known to the compiler.
>  /// - Note: Generic code should usually use `==` to compare 
>  ///   conforming instances; that will always dispatch to `===` 
>  ///   and will be unaffected by more specific overloads of
>  ///   `==`.
>  protocol Identifiable { // née Equatable name is negotiable
>func ===(_: Self, _: aSelf) -> Bool
>  }
> 
>  /// Default definition of `==` for Identifiable types.
>  func ==(lhs: T, rhs: T) -> Bool {
>return lhs === rhs
>  }
> 
>  /// Conforming types have a default total ordering.
>  /// 
>  /// If `a` and `b` are of type `Self`, `a <=> b` means that
>  /// `a` and `b` are interchangeable in most code.  A conforming 
>  /// type can document that specific observable characteristics
>  /// (such as the `capacity` of an `Array`) are inessential and 
>  /// thus not to be considered as part of the interchangeability 
>  /// guarantee.
>  ///
>  /// - Requires: `<=>` induces a total ordering over
>  ///   instances.
>  /// - Requires: the semantics of `<=>` 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Dave Abrahams via swift-evolution

on Fri Jul 22 2016, Daniel Duan  wrote:

>> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution 
>>  wrote:
>> 
>> 
>> on Fri Jul 22 2016, Daniel Duan > > wrote:
>> 
>
 On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
 > wrote:
 
 
 on Thu Jul 21 2016, Duan
>>> 
 
 >>
 wrote:
 
> Great proposal. I want to second that areSame may mislead user to
> think this is about identity.
> 
> I like areEquivalent() but there may be better names.
 
 It really *is* about identity as I posted in a previous message.  But
 that doesn't change the fact that areEquivalent might be a better name.
 It's one of the things we considered; it just seemed long for no real
 benefit.
 
>>> 
>>> If the addresses of the arguments aren’t being used, then we don’t consider
>>> them part of their *identity*. I can follow this logic. My fear is most 
>>> users
>>> won’t make this leap on their own and get the same initial impression as I 
>>> did.
>>> It's entirely possible this fear is unfounded. Some educated bikesheding
>>> wouldn't hurt here IMO :)
>> 
>> Well, it's still a very real question whether we ought to have the
>> additional API surface implied by areSame, or wether we should collapse
>> it with ===.
>> 
>
> To spell this out (because I had to think about it for a second): === will be 
> derived from
> <=>, 
> but also becomes default implementation for ==, which remains open for
> customization.

I was imagining roughly this (untested):

  /// Two references are identical if they refer to the same
  /// instance.
  ///
  /// - Note: Classes with a more-refined notion of “identical” 
  ///   should conform to `Identifiable` and implement `===`.
  func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {
ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
  }

  /// Supports testing that two values of `Self` are identical
  ///
  /// If `a` and `b` are of type `Self`, `a === b` means that
  /// `a` and `b` are interchangeable in most code.  A conforming 
  /// type can document that specific observable characteristics
  /// (such as the `capacity` of an `Array`) are inessential and 
  /// thus not to be considered as part of the interchangeability 
  /// guarantee.
  ///
  /// - Requires: `===` induces an equivalence relation over
  ///   instances.
  /// - Note: conforming types will gain an `==` operator that 
  ///   forwards to `===`.  
  /// - Note: Types that require domain-specific `==` 
  ///   implementations with different semantics (e.g. floating 
  ///   point) should define a more-specific overload of `==`, 
  ///   which will be used in contexts where the static type is
  ///   known to the compiler.
  /// - Note: Generic code should usually use `==` to compare 
  ///   conforming instances; that will always dispatch to `===` 
  ///   and will be unaffected by more specific overloads of
  ///   `==`.
  protocol Identifiable { // née Equatable name is negotiable
func ===(_: Self, _: aSelf) -> Bool
  }

  /// Default definition of `==` for Identifiable types.
  func ==(lhs: T, rhs: T) -> Bool {
return lhs === rhs
  }

  /// Conforming types have a default total ordering.
  /// 
  /// If `a` and `b` are of type `Self`, `a <=> b` means that
  /// `a` and `b` are interchangeable in most code.  A conforming 
  /// type can document that specific observable characteristics
  /// (such as the `capacity` of an `Array`) are inessential and 
  /// thus not to be considered as part of the interchangeability 
  /// guarantee.
  ///
  /// - Requires: `<=>` induces a total ordering over
  ///   instances.
  /// - Requires: the semantics of `<=>` are  consistent with
  ///   those of `===`.  That is, `(a <=> b) == .equivalent` 
  ///   iff `a === b`.
  /// - Note: conforming types will gain `<`, `<=`, `>`, and `>=` 
  ///   operators defined in terms of `<=>`.  
  /// - Note: Types that require domain-specific `<`, etc.
  ///   implementations with different semantics (e.g. floating 
  ///   point) should define more-specific overloads of those 
  ///   operators, which will be used in contexts where the 
  ///   static type is known to the compiler.
  /// - Note: Generic code can freely use `<=>` or the traditional
  ///   comparison operators to compare conforming instances; 
  ///   the result will always be supplied by `<=>` 
  ///   and will be unaffected by more specific overloads of
  ///   the other operators.
  protocol Comparable : Identifiable {
func <=> (lhs: Self, rhs: Self) -> Ordering
  }

  /// Default implementations of `<`, `<=`, `>`, and `>=`.
  extension Comparable {
static func <(lhs: Self, rhs: Self) -> Bool {
  return 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Xiaodi Wu via swift-evolution
I'm convinced. Let's make areSame === again!

On Fri, Jul 22, 2016 at 18:55 Daniel Duan via swift-evolution <
swift-evolution@swift.org> wrote:

> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>
> on Fri Jul 22 2016, Daniel Duan  wrote:
>
> On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
>  wrote:
>
>
> on Thu Jul 21 2016, Duan
>
>
>  >>
> wrote:
>
> Great proposal. I want to second that areSame may mislead user to
> think this is about identity.
>
> I like areEquivalent() but there may be better names.
>
>
> It really *is* about identity as I posted in a previous message.  But
> that doesn't change the fact that areEquivalent might be a better name.
> It's one of the things we considered; it just seemed long for no real
> benefit.
>
>
> If the addresses of the arguments aren’t being used, then we don’t consider
> them part of their *identity*. I can follow this logic. My fear is most
> users
> won’t make this leap on their own and get the same initial impression as I
> did.
> It's entirely possible this fear is unfounded. Some educated bikesheding
> wouldn't hurt here IMO :)
>
>
> Well, it's still a very real question whether we ought to have the
> additional API surface implied by areSame, or wether we should collapse
> it with ===.
>
>
> To spell this out (because I had to think about it for a second): === will
> be derived from
> <=>, but also becomes default implementation for ==, which remains open
> for customization.
>
> I like this idea. If we keep === as a separate thing, now users have 3
> “opportunities” to define
> equality. The must be few, if any, use cases for this.
>
> Would love to see if anyone on the list can give us an example. Otherwise
> we should make
> areSame === again™!
>
>
> Daniel Duan
> Sent from my iPhone
>
> On Jul 21, 2016, at 6:32 PM, Robert Widmann via swift-evolution
>  wrote:
>
>
> On Jul 21, 2016, at 6:19 PM, Xiaodi Wu  wrote:
>
> This is nice. Is `areSame()` being proposed because static `==` is
> the status quo and you're trying to make the point that `==` in the
> future need not guarantee the same semantics?
>
>
> Yep!  Equivalence and equality are strictly very different things.
>
>
> Nit: I think the more common term in stdlib would be
> `areEquivalent()`. Do you think `same` in that context (independent
> of the word "ordering") might erroneously suggest identity?
>
>
> There is room for improvement here.  Keep ‘em coming.
>
>
>
> On Thu, Jul 21, 2016 at 8:11 PM, Robert Widmann via
> swift-evolution
>  wrote:
> Hello Swift Community,
>
> Harlan Haskins, Jaden Geller, and I have been working on a
> proposal to clean up the semantics of ordering relations in the
> standard library.  We have a draft that you can get as a gist.
> Any feedback you might have about this proposal helps - though
> please keeps your comments on Swift-Evolution and not on the gist.
>
> Cheers,
>
> ~Robert Widmann
>
>
>
>
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> --
> Dave
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> >
> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> --
> Dave
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Xiaodi Wu via swift-evolution
Sorry, yeah, that's what I meant to ask. I can't see how it would make
anything unworkable, but I agree that it might not be very useful.
On Fri, Jul 22, 2016 at 18:50 Dave Abrahams via swift-evolution <
swift-evolution@swift.org> wrote:

>
> on Fri Jul 22 2016, Xiaodi Wu  wrote:
>
> > On Fri, Jul 22, 2016 at 5:48 PM, Dave Abrahams via swift-evolution <
> > swift-evolution@swift.org> wrote:
> >
> >>
> >> on Fri Jul 22 2016, Xiaodi Wu  wrote:
> >>
> >> > On Fri, Jul 22, 2016 at 3:54 PM, Dave Abrahams 
> >> wrote:
> >> >
> >> >>
> >> >> on Fri Jul 22 2016, Xiaodi Wu  wrote:
> >> >>
> >> >> > On Fri, Jul 22, 2016 at 1:05 PM, Dave Abrahams via swift-evolution
> <
> >> >> > swift-evolution@swift.org> wrote:
> >> >> >
> >> >> >>
> >> >> >> on Thu Jul 21 2016, Duan  wrote:
> >> >> >>
> >> >> >> > Great proposal. I want to second that areSame may mislead user
> to
> >> >> >> > think this is about identity.
> >> >> >> >
> >> >> >> > I like areEquivalent() but there may be better names.
> >> >> >>
> >> >> >> It really *is* about identity as I posted in a previous message.
> >> >> >
> >> >> > Correct me if I'm wrong:
> >> >>
> >> >> Not to put too fine a point on it, but... ;-)
> >> >>
> >> >
> >> > Please do :) This discussion has been very edifying (for me), so thank
> >> you
> >> > for taking the time.
> >> >
> >> >> > Identity is an equality relation, and `==` is about just that.
> >> >> > By contrast, `areSame()` is to define an *equivalence* relation
> >> >>
> >> >> The phrase “equality relation” has no commonly-understood formal or
> >> >> informal meaning AFAIK.
> >> >>
> >> >> “Identity” is a slightly informal term IIUC, but for any
> >> >> commonly-understood meaning of that word, the “is identical to” is
> >> >> *always* an equivalence relation.
> >> >>
> >> >> > through which, by default, `==` is to be dispatched.
> >> >> > Since this design specifically
> >> >> > contemplates scenarios in which certain Equatables will override
> `==`
> >> >> *not*
> >> >> > to dispatch through `areSame()`,
> >> >>
> >> >> [Since `==` wouldn't be a protocol requirement (except in
> >> FloatingPoint),
> >> >> it's technically shadowing rather than overriding in the general
> case.
> >> >> I imagine this detail doesn't matter to your point]
> >> >>
> >> >> > the latter function evaluates only *equivalence* with respect to an
> >> >> > arbitrary equivalence relation, not identity.
> >> >>
> >> >> Saying that areSame is just any old arbitrary equivalence relation,
> >> >> would complicate the system in undesirable ways.
> >> >
> >> > Ah, well, there goes my dream of using `{ return true }` as my
> >> equivalence
> >> > relation... :P
> >> >
> >> >> It's
> >> >> a bit subtle but I'll try to walk you through the reasoning:
> >> >>
> >> >> 1. We had a choice about whether to document that Comparable requires
> >> >>that <=> be a total order or a strict weak order [A strict weak
> order
> >> >>is a total order over equivalence classes of elements that aren't
> >> >>ordered with respect to other members of the same class].  Either
> one
> >> >>will work for the standard algorithms.
> >> >>
> >> >> 2. Because the concept of total order is more accessible and
> requiring
> >> >><=> to be a total order doesn't seem to reduce expressivity, we
> >> >>decided on a total order.
> >> >>
> >> >> 3. The only difference between these two orderings is that in a total
> >> >>order the equivalence classes have only a single element, **which
> >> >>means that the equivalence relation in play has to, in some sense,
> >> >>tell you whether two things are identical**.  This all comes down
> to
> >> >>how you measure “are a and b the same element?”
> >> >>
> >> >> The alternative is to say that <=> is just a strict weak ordering and
> >> >> areSame is just any arbitrary equivalence relation, but that really
> >> >> complicates everything (not just the definition of Comparable).  For
> >> >> example, you can't document `a.firstIndex(of: b)` as the first index
> >> where
> >> >> `b` appears in `a`; you have to say it's the first index of an
> element
> >> >> that satisfies `{ Element.areSame($0, b) }`.
> >> >>
> >> >
> >> > I hadn't considered how closely yoked Equatable and Comparable have
> >> > to be.  You can't have Comparable refine Equatable such that
> >> > `Comparable.areSame(_:)` has stricter semantic requirements than
> >> > plain Equatable?
> >>
> >> Not if you want algorithms requiring Equatable to make sense.  There's
> >> just no use for anything weaker than an equivalence relation.
> >>
> >
> > I'm assuming you mean:
> > s/equivalence relation/identity/
>
> No, meant what I wrote, but maybe I misunderstood your question.  I
> guess you were suggesting that `Equatable.areSame` could define an
> equivalence relation but that `<=>` might distinguish elements that
> weren't distinguished by 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Daniel Duan via swift-evolution

> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution 
>  wrote:
> 
> 
> on Fri Jul 22 2016, Daniel Duan  > wrote:
> 
>>> On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
>>> > wrote:
>>> 
>>> 
>>> on Thu Jul 21 2016, Duan
>> 
>>> 
>>> >>
>>> wrote:
>>> 
 Great proposal. I want to second that areSame may mislead user to
 think this is about identity.
 
 I like areEquivalent() but there may be better names.
>>> 
>>> It really *is* about identity as I posted in a previous message.  But
>>> that doesn't change the fact that areEquivalent might be a better name.
>>> It's one of the things we considered; it just seemed long for no real
>>> benefit.
>>> 
>> 
>> If the addresses of the arguments aren’t being used, then we don’t consider
>> them part of their *identity*. I can follow this logic. My fear is most users
>> won’t make this leap on their own and get the same initial impression as I 
>> did.
>> It's entirely possible this fear is unfounded. Some educated bikesheding
>> wouldn't hurt here IMO :)
> 
> Well, it's still a very real question whether we ought to have the
> additional API surface implied by areSame, or wether we should collapse
> it with ===.
> 

To spell this out (because I had to think about it for a second): === will be 
derived from
<=>, but also becomes default implementation for ==, which remains open for 
customization.

I like this idea. If we keep === as a separate thing, now users have 3 
“opportunities” to define
equality. The must be few, if any, use cases for this.

Would love to see if anyone on the list can give us an example. Otherwise we 
should make
areSame === again™!

>> 
 Daniel Duan
 Sent from my iPhone
 
> On Jul 21, 2016, at 6:32 PM, Robert Widmann via swift-evolution
>  wrote:
> 
> 
>> On Jul 21, 2016, at 6:19 PM, Xiaodi Wu  wrote:
>> 
>> This is nice. Is `areSame()` being proposed because static `==` is
>> the status quo and you're trying to make the point that `==` in the
>> future need not guarantee the same semantics?
> 
> Yep!  Equivalence and equality are strictly very different things.
> 
>> 
>> Nit: I think the more common term in stdlib would be
>> `areEquivalent()`. Do you think `same` in that context (independent
>> of the word "ordering") might erroneously suggest identity?
> 
> There is room for improvement here.  Keep ‘em coming.
> 
>> 
>> 
>>> On Thu, Jul 21, 2016 at 8:11 PM, Robert Widmann via
>>> swift-evolution
>>>  wrote:
>>> Hello Swift Community,
>>> 
>>> Harlan Haskins, Jaden Geller, and I have been working on a
>>> proposal to clean up the semantics of ordering relations in the
>>> standard library.  We have a draft that you can get as a gist.
>>> Any feedback you might have about this proposal helps - though
>>> please keeps your comments on Swift-Evolution and not on the gist.
>>> 
>>> Cheers,
>>> 
>>> ~Robert Widmann
>>> 
>>> 
>>> 
>>> 
>>> 
>>> ___
>>> swift-evolution mailing list
>>> swift-evolution@swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>> 
>> 
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
 ___
 swift-evolution mailing list
 swift-evolution@swift.org
 https://lists.swift.org/mailman/listinfo/swift-evolution
 
>>> 
>>> -- 
>>> Dave
>>> 
>>> ___
>>> swift-evolution mailing list
>>> swift-evolution@swift.org
>>> >
>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>> 
>>> >> >
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org 
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> 
>> 
> 
> -- 
> Dave
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org 
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Dave Abrahams via swift-evolution

on Fri Jul 22 2016, Xiaodi Wu  wrote:

> On Fri, Jul 22, 2016 at 5:48 PM, Dave Abrahams via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>>
>> on Fri Jul 22 2016, Xiaodi Wu  wrote:
>>
>> > On Fri, Jul 22, 2016 at 3:54 PM, Dave Abrahams 
>> wrote:
>> >
>> >>
>> >> on Fri Jul 22 2016, Xiaodi Wu  wrote:
>> >>
>> >> > On Fri, Jul 22, 2016 at 1:05 PM, Dave Abrahams via swift-evolution <
>> >> > swift-evolution@swift.org> wrote:
>> >> >
>> >> >>
>> >> >> on Thu Jul 21 2016, Duan  wrote:
>> >> >>
>> >> >> > Great proposal. I want to second that areSame may mislead user to
>> >> >> > think this is about identity.
>> >> >> >
>> >> >> > I like areEquivalent() but there may be better names.
>> >> >>
>> >> >> It really *is* about identity as I posted in a previous message.
>> >> >
>> >> > Correct me if I'm wrong:
>> >>
>> >> Not to put too fine a point on it, but... ;-)
>> >>
>> >
>> > Please do :) This discussion has been very edifying (for me), so thank
>> you
>> > for taking the time.
>> >
>> >> > Identity is an equality relation, and `==` is about just that.
>> >> > By contrast, `areSame()` is to define an *equivalence* relation
>> >>
>> >> The phrase “equality relation” has no commonly-understood formal or
>> >> informal meaning AFAIK.
>> >>
>> >> “Identity” is a slightly informal term IIUC, but for any
>> >> commonly-understood meaning of that word, the “is identical to” is
>> >> *always* an equivalence relation.
>> >>
>> >> > through which, by default, `==` is to be dispatched.
>> >> > Since this design specifically
>> >> > contemplates scenarios in which certain Equatables will override `==`
>> >> *not*
>> >> > to dispatch through `areSame()`,
>> >>
>> >> [Since `==` wouldn't be a protocol requirement (except in
>> FloatingPoint),
>> >> it's technically shadowing rather than overriding in the general case.
>> >> I imagine this detail doesn't matter to your point]
>> >>
>> >> > the latter function evaluates only *equivalence* with respect to an
>> >> > arbitrary equivalence relation, not identity.
>> >>
>> >> Saying that areSame is just any old arbitrary equivalence relation,
>> >> would complicate the system in undesirable ways.
>> >
>> > Ah, well, there goes my dream of using `{ return true }` as my
>> equivalence
>> > relation... :P
>> >
>> >> It's
>> >> a bit subtle but I'll try to walk you through the reasoning:
>> >>
>> >> 1. We had a choice about whether to document that Comparable requires
>> >>that <=> be a total order or a strict weak order [A strict weak order
>> >>is a total order over equivalence classes of elements that aren't
>> >>ordered with respect to other members of the same class].  Either one
>> >>will work for the standard algorithms.
>> >>
>> >> 2. Because the concept of total order is more accessible and requiring
>> >><=> to be a total order doesn't seem to reduce expressivity, we
>> >>decided on a total order.
>> >>
>> >> 3. The only difference between these two orderings is that in a total
>> >>order the equivalence classes have only a single element, **which
>> >>means that the equivalence relation in play has to, in some sense,
>> >>tell you whether two things are identical**.  This all comes down to
>> >>how you measure “are a and b the same element?”
>> >>
>> >> The alternative is to say that <=> is just a strict weak ordering and
>> >> areSame is just any arbitrary equivalence relation, but that really
>> >> complicates everything (not just the definition of Comparable).  For
>> >> example, you can't document `a.firstIndex(of: b)` as the first index
>> where
>> >> `b` appears in `a`; you have to say it's the first index of an element
>> >> that satisfies `{ Element.areSame($0, b) }`.
>> >>
>> >
>> > I hadn't considered how closely yoked Equatable and Comparable have
>> > to be.  You can't have Comparable refine Equatable such that
>> > `Comparable.areSame(_:)` has stricter semantic requirements than
>> > plain Equatable?
>>
>> Not if you want algorithms requiring Equatable to make sense.  There's
>> just no use for anything weaker than an equivalence relation.
>>
>
> I'm assuming you mean:
> s/equivalence relation/identity/

No, meant what I wrote, but maybe I misunderstood your question.  I
guess you were suggesting that `Equatable.areSame` could define an
equivalence relation but that `<=>` might distinguish elements that
weren't distinguished by `Equatable.areSame`?

Personally I don't see a use for that.  Remember, `Equatable` and
`Comparable` just define the default comparisons that you get when you
don't explicitly supply a comparison closure to these algorithms.
You're always free to use an arbitrary equivalence relation or strict
weak ordering with the closure-accepting versions of the algorithms.

> In that case, I'd think collapsing `areSame(_:)` into `===` and furnishing
> some other way of comparing memory 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Dave Abrahams via swift-evolution

on Fri Jul 22 2016, Matthew Johnson  wrote:

>> On Jul 22, 2016, at 4:47 PM, Dave Abrahams via swift-evolution
>>  wrote:
>> 
>> 
>> on Fri Jul 22 2016, Tony Allevato
>
>> > >
>> wrote:
>> 
>>> I like a lot of this, but the changes to Equatable are where I get stuck.
>>> What are the scenarios where areSame is useful *outside* the context of the
>>> proposed new Comparable interface?
>>> 
>>> I ask because changing the requirement for Equatable to areSame instead of
>>> == seems like a backwards change to me. There are plenty of unorderable
>>> types where == is the obvious thing you want to implement, and this makes
>>> it less obvious. It also adds a named method to a protocol to serve the
>>> purpose of an operator, which I've been fighting hard against in SE-0091
>>> (even though you keep the global one and delegate to it).
>>> 
>>> There are two concepts at play here: comparability and orderability. 99.99%
>>> of the time, they are identical. 
>> 
>> The concepts are “domain-specific semantics” vs “semantics that is
>> useful in generic contexts.”  Yes, they are usually identical.
>> 
>>> Your proposal mentions one place where they're not: IEEE floating
>>> point numbers, because there exists an element in that space, NaN,
>>> that doesn't satisfy an equivalence relation at all.  
>> 
>> It's not limited to NaN.  The +0/-0 distinction can be tricky as well.
>> 
>>> But it's still reasonable to want a stable ordering with those
>>> included.
>> 
>> It's also reasonable to want to search for those in a collection or use
>> them as hash keys.  I'm pointing this out because it goes to the
>> definition of equality, which sorting in general does not.
>> 
>>> In the proposal as it's written right now, the individual inequality
>>> operators are implemented in terms of <=>. That won't work for
>>> FloatingPoint, because (NaN < x) and (NaN >= x) should both be false but
>>> the default implementations provided would make the latter true. So
>>> FloatingPoint would still have to provide its own implementations of *all
>>> of the (in)equality operators*, not just ==, in order to have the correct
>>> definition w.r.t. to IEEE 754. I didn't see that called out anywhere in the
>>> write-up.
>> 
>> That's my error, actually. I wasn't thinking straight when I proposed a
>> change to the proposal that I claimed dropped the need for the other
>> operators.
>> 
>>> That being said, don't get me wrong—there's still a lot about this proposal
>>> that I like :)  Here's what I'm thinking (which is mostly what you have
>>> written, with some tweaks):
>>> 
>>> 1) Don't change Equatable. I don't see a need to distinguish between
>>> equivalence and equality on its own (if there is one, please let me
>>> know!).
>> 
>> There is, because for algorithms that require Equatable to have any kind
>> of meaningful semantics the equivalence relation requirement must be
>> fulfilled, and prominent types exist whose `==` operator is not an
>> equivalence relation.
>
> Have you considered moving away from `==` for these domain specific
> operations?  

Yes, but I think it would be a nonstarter for people who write numeric
code.

> Does the IEEE standard specify the exact syntax of `==` or is that
> just a convention?

I'm not sure.  It seems unlikely that it's an exact syntax requirement.
Steve?

> It feels really strange to me to have an `==` operation that is not an
> equivalence relation (even if it is common and is the usual way to
> compare floating point).  

Don't I know it!

> Despite common practice I think it lends itself to an intuition of
> equivalence.
>
>> 
>>> As it stands today, I think the proposal "leaks" ordering concepts into
>>> Equatable when it shouldn't.
>> 
>> I don't see any evidence for that, and I don't even believe you've said
>> anything here to support that point of view.
>> 
>>> 2) Comparable defines <=>, as proposed, but *also* defines <, >, <=, >=. A
>>> protocol extension provides defaults for <, >, <=, >=, ==, and !=
>>> implemented in terms of <=>. This lets most implementors of Comparable
>>> implement <=> and get everything else for free, but it also lets types
>>> replace individual operators with customized implementations (see #4 below)
>>> easily *within* the type (SE-0091).
>> 
>> Check
>> 
>>> 3) Comparable should be documented to imply that the default behavior is to
>>> link the behavior of <=> to the individual comparisons, but that it can be
>>> changed, meaning that only <=> must define a total ordering and the
>>> individual comparison operators need not.
>> 
>> Yes, the doc comments are missing from the proposal.
>> 
>>> 4) The very few types, like FloatingPoint, that need to provide
>>> domain-specific behavior to do the obvious/intended thing for users can and
>>> should override <, >, <=, >=, ==, and !=. This should be called out
>>> explicitly, and it would *not* 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Xiaodi Wu via swift-evolution
On Fri, Jul 22, 2016 at 6:13 PM, Stephen Canon  wrote:

> On Jul 22, 2016, at 6:55 PM, Matthew Johnson 
> wrote:
>
>
> On Jul 22, 2016, at 5:50 PM, Stephen Canon  wrote:
>
> On Jul 22, 2016, at 6:34 PM, Matthew Johnson via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>
> Sorry if it wasn’t clear.  I’m not suggesting taking that away.  I’m
> asking whether we have considered defining `==` on floating point types to
> be the equivalence relation that is proposed for `areSame` and giving the
> domain specific operation a different name.
>
> Maybe this would break with convention too much, but it would feel much
> more intuitive (to me at least - although I am admittedly not a numerics
> expert).
>
>
> IEEE754 doesn’t specify language bindings, so it *is* allowed to e.g.
> provide an `isEqualIEEE754` predicate and make `==` do something else.
>
> However, doing so would break with the precedent set by … well, every
> mainstream programming language of the past 30 years, and make porting
> existing numeric code an error-prone process for anyone who hadn’t
> carefully studied this particular aspect of Swift.
>
>
> Thanks for chiming in Steve.  I know it isn’t a decision to be taken
> lightly for sure and breaking the convention may well not be the right
> idea.  I just wanted to point out that maybe it is possible to consider
> this without giving up IEEE floating point conformance.
>
> The fact that `==` isn’t always an equivalence relation makes me sad but
> maybe the industry is too far down that rabbit hole to consider anything
> else…
>
>
> The two *major* issues I foresee with doing this both have to do with
> implementing / porting existing code.
>
> 1. There exists an enormous amount of code (and pseudo-code in
> publications) that predates the existence of `isnan` in whatever language
> the code was written with.  These codes explicitly use `x != x` as a test
> for NaN, and `x == x` as a check for non-NaN.  Users transcribing / porting
> such code are unlikely to know that they need to change these statements,
> frequently resulting in bugs that they won’t find unless their test set
> contains explicitly invalid inputs.
>
> 2. I don’t think it would make sense to make `==` an equivalence relation
> without also making `<` a strict total order.  This would cause bigger
> problems than `==`, because a lot of numeric code uses something like:
>
> while (residual > tolerance) {
> // refine
> }
>
> to check for convergence, with a test for NaN following the loop to detect
> failures; if `<` is made a strict total order, then `NaN` needs to be
> ordered either before or after finite numbers, and either option will break
> some loops written in this form.
>
> This sort of code is frequently copied out of books like “Numerical
> Recipes” with minimal adaptation to whatever the target language is, and
> even minimal awareness of the precise semantics of the target language.
> The great success of IEEE 754 is that this doesn’t *usually* matter; the
> code works anyway.  Breaking that property seems somewhat antithetical to
> the safety goals of the language.
>

Not just porting of existing code: since no modern language has changed the
meaning of `==` and `<`, it will not even occur to someone coming from
another language that this is something for which they will need to develop
an awareness while writing new code in Swift. The possibility of changing
these operators in subtle ways that break correctness of
already-implemented algorithms makes my hair stand on end. (I could not
ensure my Swift code will be correct past the current Swift 3 betas, for
example, short of ceasing to use all standard operators for floating point.)

There’s also a lesser performance concern (we have 35 years of
> floating-point hardware designed around the IEEE 754 comparison operators;
> so doing almost anything else will produce small performance hiccups on
> most hardware, and large performance issues on some hardware).  This isn’t
> my major worry, however; we’re trying to design a language for the *next*
> 35 years (or more), after all, and most of that hardware hasn’t been
> designed yet.
>
> – Steve
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Stephen Canon via swift-evolution
> On Jul 22, 2016, at 6:55 PM, Matthew Johnson  wrote:
> 
>> On Jul 22, 2016, at 5:50 PM, Stephen Canon > > wrote:
>> 
>>> On Jul 22, 2016, at 6:34 PM, Matthew Johnson via swift-evolution 
>>> > wrote:
>>> 
>>> Sorry if it wasn’t clear.  I’m not suggesting taking that away.  I’m asking 
>>> whether we have considered defining `==` on floating point types to be the 
>>> equivalence relation that is proposed for `areSame` and giving the domain 
>>> specific operation a different name.  
>>> 
>>> Maybe this would break with convention too much, but it would feel much 
>>> more intuitive (to me at least - although I am admittedly not a numerics 
>>> expert).
>> 
>> IEEE754 doesn’t specify language bindings, so it *is* allowed to e.g. 
>> provide an `isEqualIEEE754` predicate and make `==` do something else.
>> 
>> However, doing so would break with the precedent set by … well, every 
>> mainstream programming language of the past 30 years, and make porting 
>> existing numeric code an error-prone process for anyone who hadn’t carefully 
>> studied this particular aspect of Swift.
> 
> Thanks for chiming in Steve.  I know it isn’t a decision to be taken lightly 
> for sure and breaking the convention may well not be the right idea.  I just 
> wanted to point out that maybe it is possible to consider this without giving 
> up IEEE floating point conformance.
> 
> The fact that `==` isn’t always an equivalence relation makes me sad but 
> maybe the industry is too far down that rabbit hole to consider anything else…

The two *major* issues I foresee with doing this both have to do with 
implementing / porting existing code.

1. There exists an enormous amount of code (and pseudo-code in publications) 
that predates the existence of `isnan` in whatever language the code was 
written with.  These codes explicitly use `x != x` as a test for NaN, and `x == 
x` as a check for non-NaN.  Users transcribing / porting such code are unlikely 
to know that they need to change these statements, frequently resulting in bugs 
that they won’t find unless their test set contains explicitly invalid inputs.

2. I don’t think it would make sense to make `==` an equivalence relation 
without also making `<` a strict total order.  This would cause bigger problems 
than `==`, because a lot of numeric code uses something like:

while (residual > tolerance) {
// refine
}

to check for convergence, with a test for NaN following the loop to detect 
failures; if `<` is made a strict total order, then `NaN` needs to be ordered 
either before or after finite numbers, and either option will break some loops 
written in this form.

This sort of code is frequently copied out of books like “Numerical Recipes” 
with minimal adaptation to whatever the target language is, and even minimal 
awareness of the precise semantics of the target language.  The great success 
of IEEE 754 is that this doesn’t *usually* matter; the code works anyway.  
Breaking that property seems somewhat antithetical to the safety goals of the 
language.

There’s also a lesser performance concern (we have 35 years of floating-point 
hardware designed around the IEEE 754 comparison operators; so doing almost 
anything else will produce small performance hiccups on most hardware, and 
large performance issues on some hardware).  This isn’t my major worry, 
however; we’re trying to design a language for the *next* 35 years (or more), 
after all, and most of that hardware hasn’t been designed yet.

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


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Xiaodi Wu via swift-evolution
On Fri, Jul 22, 2016 at 5:48 PM, Dave Abrahams via swift-evolution <
swift-evolution@swift.org> wrote:

>
> on Fri Jul 22 2016, Xiaodi Wu  wrote:
>
> > On Fri, Jul 22, 2016 at 3:54 PM, Dave Abrahams 
> wrote:
> >
> >>
> >> on Fri Jul 22 2016, Xiaodi Wu  wrote:
> >>
> >> > On Fri, Jul 22, 2016 at 1:05 PM, Dave Abrahams via swift-evolution <
> >> > swift-evolution@swift.org> wrote:
> >> >
> >> >>
> >> >> on Thu Jul 21 2016, Duan  wrote:
> >> >>
> >> >> > Great proposal. I want to second that areSame may mislead user to
> >> >> > think this is about identity.
> >> >> >
> >> >> > I like areEquivalent() but there may be better names.
> >> >>
> >> >> It really *is* about identity as I posted in a previous message.
> >> >
> >> > Correct me if I'm wrong:
> >>
> >> Not to put too fine a point on it, but... ;-)
> >>
> >
> > Please do :) This discussion has been very edifying (for me), so thank
> you
> > for taking the time.
> >
> >> > Identity is an equality relation, and `==` is about just that.
> >> > By contrast, `areSame()` is to define an *equivalence* relation
> >>
> >> The phrase “equality relation” has no commonly-understood formal or
> >> informal meaning AFAIK.
> >>
> >> “Identity” is a slightly informal term IIUC, but for any
> >> commonly-understood meaning of that word, the “is identical to” is
> >> *always* an equivalence relation.
> >>
> >> > through which, by default, `==` is to be dispatched.
> >> > Since this design specifically
> >> > contemplates scenarios in which certain Equatables will override `==`
> >> *not*
> >> > to dispatch through `areSame()`,
> >>
> >> [Since `==` wouldn't be a protocol requirement (except in
> FloatingPoint),
> >> it's technically shadowing rather than overriding in the general case.
> >> I imagine this detail doesn't matter to your point]
> >>
> >> > the latter function evaluates only *equivalence* with respect to an
> >> > arbitrary equivalence relation, not identity.
> >>
> >> Saying that areSame is just any old arbitrary equivalence relation,
> >> would complicate the system in undesirable ways.
> >
> > Ah, well, there goes my dream of using `{ return true }` as my
> equivalence
> > relation... :P
> >
> >> It's
> >> a bit subtle but I'll try to walk you through the reasoning:
> >>
> >> 1. We had a choice about whether to document that Comparable requires
> >>that <=> be a total order or a strict weak order [A strict weak order
> >>is a total order over equivalence classes of elements that aren't
> >>ordered with respect to other members of the same class].  Either one
> >>will work for the standard algorithms.
> >>
> >> 2. Because the concept of total order is more accessible and requiring
> >><=> to be a total order doesn't seem to reduce expressivity, we
> >>decided on a total order.
> >>
> >> 3. The only difference between these two orderings is that in a total
> >>order the equivalence classes have only a single element, **which
> >>means that the equivalence relation in play has to, in some sense,
> >>tell you whether two things are identical**.  This all comes down to
> >>how you measure “are a and b the same element?”
> >>
> >> The alternative is to say that <=> is just a strict weak ordering and
> >> areSame is just any arbitrary equivalence relation, but that really
> >> complicates everything (not just the definition of Comparable).  For
> >> example, you can't document `a.firstIndex(of: b)` as the first index
> where
> >> `b` appears in `a`; you have to say it's the first index of an element
> >> that satisfies `{ Element.areSame($0, b) }`.
> >>
> >
> > I hadn't considered how closely yoked Equatable and Comparable have to
> be.
> > You can't have Comparable refine Equatable such that
> > `Comparable.areSame(_:)` has stricter semantic requirements than plain
> > Equatable?
>
> Not if you want algorithms requiring Equatable to make sense.  There's
> just no use for anything weaker than an equivalence relation.
>

I'm assuming you mean:
s/equivalence relation/identity/

In that case, I'd think collapsing `areSame(_:)` into `===` and furnishing
some other way of comparing memory addresses for class types is the most
sensible way to go.


> >
> >> > Put another way, the future `Equatable` is a contract that conforming
> >> > types will supply a definition of equality *and* an equivalence
> >> > relation, where the former by default is dispatched through the
> >> > latter; but it is specifically envisioned that the two may be
> >> > separated in domain-specific scenarios.
> >>
> >> That is correct.  However, the equivalence relation in question still
> >> is, in some very real sense, an identity check.
> >>
> >> >> But
> >> >> that doesn't change the fact that areEquivalent might be a better
> name.
> >> >> It's one of the things we considered; it just seemed long for no real
> >> >> benefit.
> >> >>
> >> >> > Daniel Duan
> >> >> > Sent from my 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Matthew Johnson via swift-evolution

> On Jul 22, 2016, at 5:50 PM, Stephen Canon  wrote:
> 
>> On Jul 22, 2016, at 6:34 PM, Matthew Johnson via swift-evolution 
>> > wrote:
>> 
>> Sorry if it wasn’t clear.  I’m not suggesting taking that away.  I’m asking 
>> whether we have considered defining `==` on floating point types to be the 
>> equivalence relation that is proposed for `areSame` and giving the domain 
>> specific operation a different name.  
>> 
>> Maybe this would break with convention too much, but it would feel much more 
>> intuitive (to me at least - although I am admittedly not a numerics expert).
> 
> IEEE754 doesn’t specify language bindings, so it *is* allowed to e.g. provide 
> an `isEqualIEEE754` predicate and make `==` do something else.
> 
> However, doing so would break with the precedent set by … well, every 
> mainstream programming language of the past 30 years, and make porting 
> existing numeric code an error-prone process for anyone who hadn’t carefully 
> studied this particular aspect of Swift.

Thanks for chiming in Steve.  I know it isn’t a decision to be taken lightly 
for sure and breaking the convention may well not be the right idea.  I just 
wanted to point out that maybe it is possible to consider this without giving 
up IEEE floating point conformance.

The fact that `==` isn’t always an equivalence relation makes me sad but maybe 
the industry is too far down that rabbit hole to consider anything else...

> 
> – Steve

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


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Dave Abrahams via swift-evolution

on Fri Jul 22 2016, Xiaodi Wu  wrote:

> On Fri, Jul 22, 2016 at 3:54 PM, Dave Abrahams  wrote:
>
>>
>> on Fri Jul 22 2016, Xiaodi Wu  wrote:
>>
>> > On Fri, Jul 22, 2016 at 1:05 PM, Dave Abrahams via swift-evolution <
>> > swift-evolution@swift.org> wrote:
>> >
>> >>
>> >> on Thu Jul 21 2016, Duan  wrote:
>> >>
>> >> > Great proposal. I want to second that areSame may mislead user to
>> >> > think this is about identity.
>> >> >
>> >> > I like areEquivalent() but there may be better names.
>> >>
>> >> It really *is* about identity as I posted in a previous message.
>> >
>> > Correct me if I'm wrong:
>>
>> Not to put too fine a point on it, but... ;-)
>>
>
> Please do :) This discussion has been very edifying (for me), so thank you
> for taking the time.
>
>> > Identity is an equality relation, and `==` is about just that.
>> > By contrast, `areSame()` is to define an *equivalence* relation
>>
>> The phrase “equality relation” has no commonly-understood formal or
>> informal meaning AFAIK.
>>
>> “Identity” is a slightly informal term IIUC, but for any
>> commonly-understood meaning of that word, the “is identical to” is
>> *always* an equivalence relation.
>>
>> > through which, by default, `==` is to be dispatched.
>> > Since this design specifically
>> > contemplates scenarios in which certain Equatables will override `==`
>> *not*
>> > to dispatch through `areSame()`,
>>
>> [Since `==` wouldn't be a protocol requirement (except in FloatingPoint),
>> it's technically shadowing rather than overriding in the general case.
>> I imagine this detail doesn't matter to your point]
>>
>> > the latter function evaluates only *equivalence* with respect to an
>> > arbitrary equivalence relation, not identity.
>>
>> Saying that areSame is just any old arbitrary equivalence relation,
>> would complicate the system in undesirable ways.
>
> Ah, well, there goes my dream of using `{ return true }` as my equivalence
> relation... :P
>
>> It's
>> a bit subtle but I'll try to walk you through the reasoning:
>>
>> 1. We had a choice about whether to document that Comparable requires
>>that <=> be a total order or a strict weak order [A strict weak order
>>is a total order over equivalence classes of elements that aren't
>>ordered with respect to other members of the same class].  Either one
>>will work for the standard algorithms.
>>
>> 2. Because the concept of total order is more accessible and requiring
>><=> to be a total order doesn't seem to reduce expressivity, we
>>decided on a total order.
>>
>> 3. The only difference between these two orderings is that in a total
>>order the equivalence classes have only a single element, **which
>>means that the equivalence relation in play has to, in some sense,
>>tell you whether two things are identical**.  This all comes down to
>>how you measure “are a and b the same element?”
>>
>> The alternative is to say that <=> is just a strict weak ordering and
>> areSame is just any arbitrary equivalence relation, but that really
>> complicates everything (not just the definition of Comparable).  For
>> example, you can't document `a.firstIndex(of: b)` as the first index where
>> `b` appears in `a`; you have to say it's the first index of an element
>> that satisfies `{ Element.areSame($0, b) }`.
>>
>
> I hadn't considered how closely yoked Equatable and Comparable have to be.
> You can't have Comparable refine Equatable such that
> `Comparable.areSame(_:)` has stricter semantic requirements than plain
> Equatable?

Not if you want algorithms requiring Equatable to make sense.  There's
just no use for anything weaker than an equivalence relation.

>
>> > Put another way, the future `Equatable` is a contract that conforming
>> > types will supply a definition of equality *and* an equivalence
>> > relation, where the former by default is dispatched through the
>> > latter; but it is specifically envisioned that the two may be
>> > separated in domain-specific scenarios.
>>
>> That is correct.  However, the equivalence relation in question still
>> is, in some very real sense, an identity check.
>>
>> >> But
>> >> that doesn't change the fact that areEquivalent might be a better name.
>> >> It's one of the things we considered; it just seemed long for no real
>> >> benefit.
>> >>
>> >> > Daniel Duan
>> >> > Sent from my iPhone
>> >> >
>> >> >> On Jul 21, 2016, at 6:32 PM, Robert Widmann via swift-evolution
>> >> >>  wrote:
>> >> >>
>> >> >>
>> >> >>> On Jul 21, 2016, at 6:19 PM, Xiaodi Wu  wrote:
>> >> >>>
>> >> >>> This is nice. Is `areSame()` being proposed because static `==` is
>> >> >>> the status quo and you're trying to make the point that `==` in the
>> >> >>> future need not guarantee the same semantics?
>> >> >>
>> >> >> Yep!  Equivalence and equality are strictly very different things.
>> >> >>
>> >> >>>
>> >> >>> 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Matthew Johnson via swift-evolution

> On Jul 22, 2016, at 5:41 PM, Xiaodi Wu  wrote:
> 
> On Fri, Jul 22, 2016 at 5:34 PM, Matthew Johnson  > wrote:
> 
>> On Jul 22, 2016, at 5:29 PM, Xiaodi Wu > > wrote:
>> 
>> On Fri, Jul 22, 2016 at 5:17 PM, Matthew Johnson via swift-evolution 
>> > wrote:
>> 
>>> On Jul 22, 2016, at 4:47 PM, Dave Abrahams via swift-evolution 
>>> > wrote:
>>> 
>>> 
>>> on Fri Jul 22 2016, Tony Allevato >> > wrote:
>>> 
 I like a lot of this, but the changes to Equatable are where I get stuck.
 What are the scenarios where areSame is useful *outside* the context of the
 proposed new Comparable interface?
 
 I ask because changing the requirement for Equatable to areSame instead of
 == seems like a backwards change to me. There are plenty of unorderable
 types where == is the obvious thing you want to implement, and this makes
 it less obvious. It also adds a named method to a protocol to serve the
 purpose of an operator, which I've been fighting hard against in SE-0091
 (even though you keep the global one and delegate to it).
 
 There are two concepts at play here: comparability and orderability. 99.99%
 of the time, they are identical. 
>>> 
>>> The concepts are “domain-specific semantics” vs “semantics that is
>>> useful in generic contexts.”  Yes, they are usually identical.
>>> 
 Your proposal mentions one place where they're not: IEEE floating
 point numbers, because there exists an element in that space, NaN,
 that doesn't satisfy an equivalence relation at all.  
>>> 
>>> It's not limited to NaN.  The +0/-0 distinction can be tricky as well.
>>> 
 But it's still reasonable to want a stable ordering with those
 included.
>>> 
>>> It's also reasonable to want to search for those in a collection or use
>>> them as hash keys.  I'm pointing this out because it goes to the
>>> definition of equality, which sorting in general does not.
>>> 
 In the proposal as it's written right now, the individual inequality
 operators are implemented in terms of <=>. That won't work for
 FloatingPoint, because (NaN < x) and (NaN >= x) should both be false but
 the default implementations provided would make the latter true. So
 FloatingPoint would still have to provide its own implementations of *all
 of the (in)equality operators*, not just ==, in order to have the correct
 definition w.r.t. to IEEE 754. I didn't see that called out anywhere in the
 write-up.
>>> 
>>> That's my error, actually. I wasn't thinking straight when I proposed a
>>> change to the proposal that I claimed dropped the need for the other
>>> operators.
>>> 
 That being said, don't get me wrong—there's still a lot about this proposal
 that I like :)  Here's what I'm thinking (which is mostly what you have
 written, with some tweaks):
 
 1) Don't change Equatable. I don't see a need to distinguish between
 equivalence and equality on its own (if there is one, please let me
 know!).
>>> 
>>> There is, because for algorithms that require Equatable to have any kind
>>> of meaningful semantics the equivalence relation requirement must be
>>> fulfilled, and prominent types exist whose `==` operator is not an
>>> equivalence relation.
>> 
>> Have you considered moving away from `==` for these domain specific 
>> operations?  Does the IEEE standard specify the exact syntax of `==` or is 
>> that just a convention?
>> 
>> It feels really strange to me to have an `==` operation that is not an 
>> equivalence relation (even if it is common and is the usual way to compare 
>> floating point).  Despite common practice I think it lends itself to an 
>> intuition of equivalence.  
>> 
>> I think that would just be too disruptive. I expect to be able to compare 
>> any numeric type to the integer literal 0 using `==`.
> 
> Sorry if it wasn’t clear.  I’m not suggesting taking that away.  I’m asking 
> whether we have considered defining `==` on floating point types to be the 
> equivalence relation that is proposed for `areSame` and giving the domain 
> specific operation a different name.  
> 
> Sorry, bad example. Doing so would take away NaN != NaN. I think many users, 
> not considering implementation of their own type, would be sorely confused 
> why this already difficult concept about floating point types which they've 
> just wrapped their heads around stops working yet again.

Yes it would.  But not doing so means `==` isn’t always an equivalence 
relation.  Both are problematic IMO.  I’m posing the question which one is 
worse.  I don’t know the answer.  :)

>  
> Maybe this would break with convention too much, but it would feel 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Stephen Canon via swift-evolution
> On Jul 22, 2016, at 6:34 PM, Matthew Johnson via swift-evolution 
>  wrote:
> 
> Sorry if it wasn’t clear.  I’m not suggesting taking that away.  I’m asking 
> whether we have considered defining `==` on floating point types to be the 
> equivalence relation that is proposed for `areSame` and giving the domain 
> specific operation a different name.  
> 
> Maybe this would break with convention too much, but it would feel much more 
> intuitive (to me at least - although I am admittedly not a numerics expert).

IEEE754 doesn’t specify language bindings, so it *is* allowed to e.g. provide 
an `isEqualIEEE754` predicate and make `==` do something else.

However, doing so would break with the precedent set by … well, every 
mainstream programming language of the past 30 years, and make porting existing 
numeric code an error-prone process for anyone who hadn’t carefully studied 
this particular aspect of Swift.

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


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Xiaodi Wu via swift-evolution
On Fri, Jul 22, 2016 at 5:34 PM, Matthew Johnson 
wrote:

>
> On Jul 22, 2016, at 5:29 PM, Xiaodi Wu  wrote:
>
> On Fri, Jul 22, 2016 at 5:17 PM, Matthew Johnson via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>>
>> On Jul 22, 2016, at 4:47 PM, Dave Abrahams via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>
>> on Fri Jul 22 2016, Tony Allevato  wrote:
>>
>> I like a lot of this, but the changes to Equatable are where I get stuck.
>> What are the scenarios where areSame is useful *outside* the context of
>> the
>> proposed new Comparable interface?
>>
>> I ask because changing the requirement for Equatable to areSame instead of
>> == seems like a backwards change to me. There are plenty of unorderable
>> types where == is the obvious thing you want to implement, and this makes
>> it less obvious. It also adds a named method to a protocol to serve the
>> purpose of an operator, which I've been fighting hard against in SE-0091
>> (even though you keep the global one and delegate to it).
>>
>> There are two concepts at play here: comparability and orderability.
>> 99.99%
>> of the time, they are identical.
>>
>>
>> The concepts are “domain-specific semantics” vs “semantics that is
>> useful in generic contexts.”  Yes, they are usually identical.
>>
>> Your proposal mentions one place where they're not: IEEE floating
>> point numbers, because there exists an element in that space, NaN,
>> that doesn't satisfy an equivalence relation at all.
>>
>>
>> It's not limited to NaN.  The +0/-0 distinction can be tricky as well.
>>
>> But it's still reasonable to want a stable ordering with those
>> included.
>>
>>
>> It's also reasonable to want to search for those in a collection or use
>> them as hash keys.  I'm pointing this out because it goes to the
>> definition of equality, which sorting in general does not.
>>
>> In the proposal as it's written right now, the individual inequality
>> operators are implemented in terms of <=>. That won't work for
>> FloatingPoint, because (NaN < x) and (NaN >= x) should both be false but
>> the default implementations provided would make the latter true. So
>> FloatingPoint would still have to provide its own implementations of *all
>> of the (in)equality operators*, not just ==, in order to have the correct
>> definition w.r.t. to IEEE 754. I didn't see that called out anywhere in
>> the
>> write-up.
>>
>>
>> That's my error, actually. I wasn't thinking straight when I proposed a
>> change to the proposal that I claimed dropped the need for the other
>> operators.
>>
>> That being said, don't get me wrong—there's still a lot about this
>> proposal
>> that I like :)  Here's what I'm thinking (which is mostly what you have
>> written, with some tweaks):
>>
>> 1) Don't change Equatable. I don't see a need to distinguish between
>> equivalence and equality on its own (if there is one, please let me
>> know!).
>>
>>
>> There is, because for algorithms that require Equatable to have any kind
>> of meaningful semantics the equivalence relation requirement must be
>> fulfilled, and prominent types exist whose `==` operator is not an
>> equivalence relation.
>>
>>
>> Have you considered moving away from `==` for these domain specific
>> operations?  Does the IEEE standard specify the exact syntax of `==` or is
>> that just a convention?
>>
>> It feels really strange to me to have an `==` operation that is not an
>> equivalence relation (even if it is common and is the usual way to compare
>> floating point).  Despite common practice I think it lends itself to an
>> intuition of equivalence.
>>
>
> I think that would just be too disruptive. I expect to be able to compare
> any numeric type to the integer literal 0 using `==`.
>
>
> Sorry if it wasn’t clear.  I’m not suggesting taking that away.  I’m
> asking whether we have considered defining `==` on floating point types to
> be the equivalence relation that is proposed for `areSame` and giving the
> domain specific operation a different name.
>

Sorry, bad example. Doing so would take away NaN != NaN. I think many
users, not considering implementation of their own type, would be sorely
confused why this already difficult concept about floating point types
which they've just wrapped their heads around stops working yet again.


> Maybe this would break with convention too much, but it would feel much
> more intuitive (to me at least - although I am admittedly not a numerics
> expert).
>

IEEE does indeed suggest what standard comparison operators should do, if I
recall correctly.

> As it stands today, I think the proposal "leaks" ordering concepts into
>> Equatable when it shouldn't.
>>
>>
>> I don't see any evidence for that, and I don't even believe you've said
>> anything here to support that point of view.
>>
>> 2) Comparable defines <=>, as proposed, but *also* defines <, >, <=, >=. A
>> protocol extension provides defaults for <, >, 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Xiaodi Wu via swift-evolution
On Fri, Jul 22, 2016 at 3:54 PM, Dave Abrahams  wrote:

>
> on Fri Jul 22 2016, Xiaodi Wu  wrote:
>
> > On Fri, Jul 22, 2016 at 1:05 PM, Dave Abrahams via swift-evolution <
> > swift-evolution@swift.org> wrote:
> >
> >>
> >> on Thu Jul 21 2016, Duan  wrote:
> >>
> >> > Great proposal. I want to second that areSame may mislead user to
> >> > think this is about identity.
> >> >
> >> > I like areEquivalent() but there may be better names.
> >>
> >> It really *is* about identity as I posted in a previous message.
> >
> > Correct me if I'm wrong:
>
> Not to put too fine a point on it, but... ;-)
>

Please do :) This discussion has been very edifying (for me), so thank you
for taking the time.


> > Identity is an equality relation, and `==` is about just that.
> > By contrast, `areSame()` is to define an *equivalence* relation
>
> The phrase “equality relation” has no commonly-understood formal or
> informal meaning AFAIK.
>
> “Identity” is a slightly informal term IIUC, but for any
> commonly-understood meaning of that word, the “is identical to” is
> *always* an equivalence relation.
>
> > through which, by default, `==` is to be dispatched.
> > Since this design specifically
> > contemplates scenarios in which certain Equatables will override `==`
> *not*
> > to dispatch through `areSame()`,
>
> [Since `==` wouldn't be a protocol requirement (except in FloatingPoint),
> it's technically shadowing rather than overriding in the general case.
> I imagine this detail doesn't matter to your point]
>
> > the latter function evaluates only *equivalence* with respect to an
> > arbitrary equivalence relation, not identity.
>
> Saying that areSame is just any old arbitrary equivalence relation,
> would complicate the system in undesirable ways.


Ah, well, there goes my dream of using `{ return true }` as my equivalence
relation... :P


> It's
> a bit subtle but I'll try to walk you through the reasoning:
>
> 1. We had a choice about whether to document that Comparable requires
>that <=> be a total order or a strict weak order [A strict weak order
>is a total order over equivalence classes of elements that aren't
>ordered with respect to other members of the same class].  Either one
>will work for the standard algorithms.
>
> 2. Because the concept of total order is more accessible and requiring
><=> to be a total order doesn't seem to reduce expressivity, we
>decided on a total order.
>
> 3. The only difference between these two orderings is that in a total
>order the equivalence classes have only a single element, **which
>means that the equivalence relation in play has to, in some sense,
>tell you whether two things are identical**.  This all comes down to
>how you measure “are a and b the same element?”
>
> The alternative is to say that <=> is just a strict weak ordering and
> areSame is just any arbitrary equivalence relation, but that really
> complicates everything (not just the definition of Comparable).  For
> example, you can't document `a.firstIndex(of: b)` as the first index where
> `b` appears in `a`; you have to say it's the first index of an element
> that satisfies `{ Element.areSame($0, b) }`.
>

I hadn't considered how closely yoked Equatable and Comparable have to be.
You can't have Comparable refine Equatable such that
`Comparable.areSame(_:)` has stricter semantic requirements than plain
Equatable?


> > Put another way, the future `Equatable` is a contract that conforming
> > types will supply a definition of equality *and* an equivalence
> > relation, where the former by default is dispatched through the
> > latter; but it is specifically envisioned that the two may be
> > separated in domain-specific scenarios.
>
> That is correct.  However, the equivalence relation in question still
> is, in some very real sense, an identity check.
>
> >> But
> >> that doesn't change the fact that areEquivalent might be a better name.
> >> It's one of the things we considered; it just seemed long for no real
> >> benefit.
> >>
> >> > Daniel Duan
> >> > Sent from my iPhone
> >> >
> >> >> On Jul 21, 2016, at 6:32 PM, Robert Widmann via swift-evolution
> >> >>  wrote:
> >> >>
> >> >>
> >> >>> On Jul 21, 2016, at 6:19 PM, Xiaodi Wu  wrote:
> >> >>>
> >> >>> This is nice. Is `areSame()` being proposed because static `==` is
> >> >>> the status quo and you're trying to make the point that `==` in the
> >> >>> future need not guarantee the same semantics?
> >> >>
> >> >> Yep!  Equivalence and equality are strictly very different things.
> >> >>
> >> >>>
> >> >>> Nit: I think the more common term in stdlib would be
> >> >>> `areEquivalent()`. Do you think `same` in that context (independent
> >> >>> of the word "ordering") might erroneously suggest identity?
> >> >>
> >> >> There is room for improvement here.  Keep ‘em coming.
> >> >>
> >> >>>
> >> >>>
> >>  On Thu, Jul 21, 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Xiaodi Wu via swift-evolution
On Fri, Jul 22, 2016 at 5:17 PM, Matthew Johnson via swift-evolution <
swift-evolution@swift.org> wrote:

>
> On Jul 22, 2016, at 4:47 PM, Dave Abrahams via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>
> on Fri Jul 22 2016, Tony Allevato  wrote:
>
> I like a lot of this, but the changes to Equatable are where I get stuck.
> What are the scenarios where areSame is useful *outside* the context of the
> proposed new Comparable interface?
>
> I ask because changing the requirement for Equatable to areSame instead of
> == seems like a backwards change to me. There are plenty of unorderable
> types where == is the obvious thing you want to implement, and this makes
> it less obvious. It also adds a named method to a protocol to serve the
> purpose of an operator, which I've been fighting hard against in SE-0091
> (even though you keep the global one and delegate to it).
>
> There are two concepts at play here: comparability and orderability. 99.99%
> of the time, they are identical.
>
>
> The concepts are “domain-specific semantics” vs “semantics that is
> useful in generic contexts.”  Yes, they are usually identical.
>
> Your proposal mentions one place where they're not: IEEE floating
> point numbers, because there exists an element in that space, NaN,
> that doesn't satisfy an equivalence relation at all.
>
>
> It's not limited to NaN.  The +0/-0 distinction can be tricky as well.
>
> But it's still reasonable to want a stable ordering with those
> included.
>
>
> It's also reasonable to want to search for those in a collection or use
> them as hash keys.  I'm pointing this out because it goes to the
> definition of equality, which sorting in general does not.
>
> In the proposal as it's written right now, the individual inequality
> operators are implemented in terms of <=>. That won't work for
> FloatingPoint, because (NaN < x) and (NaN >= x) should both be false but
> the default implementations provided would make the latter true. So
> FloatingPoint would still have to provide its own implementations of *all
> of the (in)equality operators*, not just ==, in order to have the correct
> definition w.r.t. to IEEE 754. I didn't see that called out anywhere in the
> write-up.
>
>
> That's my error, actually. I wasn't thinking straight when I proposed a
> change to the proposal that I claimed dropped the need for the other
> operators.
>
> That being said, don't get me wrong—there's still a lot about this proposal
> that I like :)  Here's what I'm thinking (which is mostly what you have
> written, with some tweaks):
>
> 1) Don't change Equatable. I don't see a need to distinguish between
> equivalence and equality on its own (if there is one, please let me
> know!).
>
>
> There is, because for algorithms that require Equatable to have any kind
> of meaningful semantics the equivalence relation requirement must be
> fulfilled, and prominent types exist whose `==` operator is not an
> equivalence relation.
>
>
> Have you considered moving away from `==` for these domain specific
> operations?  Does the IEEE standard specify the exact syntax of `==` or is
> that just a convention?
>
> It feels really strange to me to have an `==` operation that is not an
> equivalence relation (even if it is common and is the usual way to compare
> floating point).  Despite common practice I think it lends itself to an
> intuition of equivalence.
>

I think that would just be too disruptive. I expect to be able to compare
any numeric type to the integer literal 0 using `==`.

> As it stands today, I think the proposal "leaks" ordering concepts into
> Equatable when it shouldn't.
>
>
> I don't see any evidence for that, and I don't even believe you've said
> anything here to support that point of view.
>
> 2) Comparable defines <=>, as proposed, but *also* defines <, >, <=, >=. A
> protocol extension provides defaults for <, >, <=, >=, ==, and !=
> implemented in terms of <=>. This lets most implementors of Comparable
> implement <=> and get everything else for free, but it also lets types
> replace individual operators with customized implementations (see #4 below)
> easily *within* the type (SE-0091).
>
>
> Check
>
> 3) Comparable should be documented to imply that the default behavior is to
> link the behavior of <=> to the individual comparisons, but that it can be
> changed, meaning that only <=> must define a total ordering and the
> individual comparison operators need not.
>
>
> Yes, the doc comments are missing from the proposal.
>
> 4) The very few types, like FloatingPoint, that need to provide
> domain-specific behavior to do the obvious/intended thing for users can and
> should override <, >, <=, >=, ==, and !=. This should be called out
> explicitly, and it would *not* affect ordering.
>
>
> Depends what you mean by “affect ordering.”  Clearly if you sort Floats
> using < explicitly, it will have an effect.
>
> I think it's entirely reasonable to have (NaN == NaN) return false 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Tony Allevato via swift-evolution
On Fri, Jul 22, 2016 at 2:52 PM Dave Abrahams via swift-evolution <
swift-evolution@swift.org> wrote:

>
> on Fri Jul 22 2016, Tony Allevato  wrote:
>
> > I like a lot of this, but the changes to Equatable are where I get stuck.
> > What are the scenarios where areSame is useful *outside* the context of
> the
> > proposed new Comparable interface?
> >
> > I ask because changing the requirement for Equatable to areSame instead
> of
> > == seems like a backwards change to me. There are plenty of unorderable
> > types where == is the obvious thing you want to implement, and this makes
> > it less obvious. It also adds a named method to a protocol to serve the
> > purpose of an operator, which I've been fighting hard against in SE-0091
> > (even though you keep the global one and delegate to it).
> >
> > There are two concepts at play here: comparability and orderability.
> 99.99%
> > of the time, they are identical.
>
> The concepts are “domain-specific semantics” vs “semantics that is
> useful in generic contexts.”  Yes, they are usually identical.
>
> > Your proposal mentions one place where they're not: IEEE floating
> > point numbers, because there exists an element in that space, NaN,
> > that doesn't satisfy an equivalence relation at all.
>
> It's not limited to NaN.  The +0/-0 distinction can be tricky as well.
>
> > But it's still reasonable to want a stable ordering with those
> > included.
>
> It's also reasonable to want to search for those in a collection or use
> them as hash keys.  I'm pointing this out because it goes to the
> definition of equality, which sorting in general does not.
>
> > In the proposal as it's written right now, the individual inequality
> > operators are implemented in terms of <=>. That won't work for
> > FloatingPoint, because (NaN < x) and (NaN >= x) should both be false but
> > the default implementations provided would make the latter true. So
> > FloatingPoint would still have to provide its own implementations of *all
> > of the (in)equality operators*, not just ==, in order to have the correct
> > definition w.r.t. to IEEE 754. I didn't see that called out anywhere in
> the
> > write-up.
>
> That's my error, actually. I wasn't thinking straight when I proposed a
> change to the proposal that I claimed dropped the need for the other
> operators.
>
> > That being said, don't get me wrong—there's still a lot about this
> proposal
> > that I like :)  Here's what I'm thinking (which is mostly what you have
> > written, with some tweaks):
> >
> > 1) Don't change Equatable. I don't see a need to distinguish between
> > equivalence and equality on its own (if there is one, please let me
> > know!).
>
> There is, because for algorithms that require Equatable to have any kind
> of meaningful semantics the equivalence relation requirement must be
> fulfilled, and prominent types exist whose `==` operator is not an
> equivalence relation.
>

Thanks for the detailed reply, Dave—this and some of your earlier replies
to this thread have helped me understand the use cases for this
distinction. So the argument is that something like this:

[ 1.0, -2.0, Double.NaN, 4.0 ].contains(Double.NaN)

should return true because the argument is in the same equivalence class as
the element, even though NaN == NaN currently returns false? That seems
totally reasonable, and I think it would be very helpful for the proposal
to specifically call out some of these scenarios—right now it focuses
mostly on ordering, which led to my confusion.

To take this further, let's say I have a data structure where the elements
are a type with multiple fields, and the ordering is determined by a single
one of those fields (the "key"). Would a reasonable definition of
equivalence in this model be one where a is equivalent to b if a.key ==
b.key, regardless of the values of the other fields, and equality is
implemented by comparing all the fields? This is similar to how C++ STL's
definition of equivalence for ordered collections falls out of the
expression !(a < b) && !(b < a), since you could conceivably implement <
and == with the same distinctions there.

I would be completely supportive of using `===` for this equivalence
instead of areSame, based on your argument about identity. Would we need an
escape hatch for people who absolutely need to know whether two instances
occupy the same address? If I had to choose equivalence vs. same-address as
the one to make more verbose, same-address seems like the obvious choice to
me.



> > As it stands today, I think the proposal "leaks" ordering concepts into
> > Equatable when it shouldn't.
>
> I don't see any evidence for that, and I don't even believe you've said
> anything here to support that point of view.
>
> > 2) Comparable defines <=>, as proposed, but *also* defines <, >, <=, >=.
> A
> > protocol extension provides defaults for <, >, <=, >=, ==, and !=
> > implemented in terms of <=>. This lets most implementors of Comparable

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Matthew Johnson via swift-evolution

> On Jul 22, 2016, at 4:47 PM, Dave Abrahams via swift-evolution 
>  wrote:
> 
> 
> on Fri Jul 22 2016, Tony Allevato  > wrote:
> 
>> I like a lot of this, but the changes to Equatable are where I get stuck.
>> What are the scenarios where areSame is useful *outside* the context of the
>> proposed new Comparable interface?
>> 
>> I ask because changing the requirement for Equatable to areSame instead of
>> == seems like a backwards change to me. There are plenty of unorderable
>> types where == is the obvious thing you want to implement, and this makes
>> it less obvious. It also adds a named method to a protocol to serve the
>> purpose of an operator, which I've been fighting hard against in SE-0091
>> (even though you keep the global one and delegate to it).
>> 
>> There are two concepts at play here: comparability and orderability. 99.99%
>> of the time, they are identical. 
> 
> The concepts are “domain-specific semantics” vs “semantics that is
> useful in generic contexts.”  Yes, they are usually identical.
> 
>> Your proposal mentions one place where they're not: IEEE floating
>> point numbers, because there exists an element in that space, NaN,
>> that doesn't satisfy an equivalence relation at all.  
> 
> It's not limited to NaN.  The +0/-0 distinction can be tricky as well.
> 
>> But it's still reasonable to want a stable ordering with those
>> included.
> 
> It's also reasonable to want to search for those in a collection or use
> them as hash keys.  I'm pointing this out because it goes to the
> definition of equality, which sorting in general does not.
> 
>> In the proposal as it's written right now, the individual inequality
>> operators are implemented in terms of <=>. That won't work for
>> FloatingPoint, because (NaN < x) and (NaN >= x) should both be false but
>> the default implementations provided would make the latter true. So
>> FloatingPoint would still have to provide its own implementations of *all
>> of the (in)equality operators*, not just ==, in order to have the correct
>> definition w.r.t. to IEEE 754. I didn't see that called out anywhere in the
>> write-up.
> 
> That's my error, actually. I wasn't thinking straight when I proposed a
> change to the proposal that I claimed dropped the need for the other
> operators.
> 
>> That being said, don't get me wrong—there's still a lot about this proposal
>> that I like :)  Here's what I'm thinking (which is mostly what you have
>> written, with some tweaks):
>> 
>> 1) Don't change Equatable. I don't see a need to distinguish between
>> equivalence and equality on its own (if there is one, please let me
>> know!).
> 
> There is, because for algorithms that require Equatable to have any kind
> of meaningful semantics the equivalence relation requirement must be
> fulfilled, and prominent types exist whose `==` operator is not an
> equivalence relation.

Have you considered moving away from `==` for these domain specific operations? 
 Does the IEEE standard specify the exact syntax of `==` or is that just a 
convention?

It feels really strange to me to have an `==` operation that is not an 
equivalence relation (even if it is common and is the usual way to compare 
floating point).  Despite common practice I think it lends itself to an 
intuition of equivalence.  



> 
>> As it stands today, I think the proposal "leaks" ordering concepts into
>> Equatable when it shouldn't.
> 
> I don't see any evidence for that, and I don't even believe you've said
> anything here to support that point of view.
> 
>> 2) Comparable defines <=>, as proposed, but *also* defines <, >, <=, >=. A
>> protocol extension provides defaults for <, >, <=, >=, ==, and !=
>> implemented in terms of <=>. This lets most implementors of Comparable
>> implement <=> and get everything else for free, but it also lets types
>> replace individual operators with customized implementations (see #4 below)
>> easily *within* the type (SE-0091).
> 
> Check
> 
>> 3) Comparable should be documented to imply that the default behavior is to
>> link the behavior of <=> to the individual comparisons, but that it can be
>> changed, meaning that only <=> must define a total ordering and the
>> individual comparison operators need not.
> 
> Yes, the doc comments are missing from the proposal.
> 
>> 4) The very few types, like FloatingPoint, that need to provide
>> domain-specific behavior to do the obvious/intended thing for users can and
>> should override <, >, <=, >=, ==, and !=. This should be called out
>> explicitly, and it would *not* affect ordering. 
> 
> Depends what you mean by “affect ordering.”  Clearly if you sort Floats
> using < explicitly, it will have an effect.
> 
>> I think it's entirely reasonable to have (NaN == NaN) return false and
>> (NaN != NaN) return true but (NaN <=> NaN) return .same without
>> introducing another areSame concept, because the former is demanded by
>> 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Dave Abrahams via swift-evolution

on Fri Jul 22 2016, Daniel Duan  wrote:

>> On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution
>>  wrote:
>> 
>> 
>> on Thu Jul 21 2016, Duan
>
>> > >
>> wrote:
>> 
>>> Great proposal. I want to second that areSame may mislead user to
>>> think this is about identity.
>>> 
>>> I like areEquivalent() but there may be better names.
>> 
>> It really *is* about identity as I posted in a previous message.  But
>> that doesn't change the fact that areEquivalent might be a better name.
>> It's one of the things we considered; it just seemed long for no real
>> benefit.
>> 
>
> If the addresses of the arguments aren’t being used, then we don’t consider
> them part of their *identity*. I can follow this logic. My fear is most users
> won’t make this leap on their own and get the same initial impression as I 
> did.
> It's entirely possible this fear is unfounded. Some educated bikesheding
> wouldn't hurt here IMO :)

Well, it's still a very real question whether we ought to have the
additional API surface implied by areSame, or wether we should collapse
it with ===.

>
>>> Daniel Duan
>>> Sent from my iPhone
>>> 
 On Jul 21, 2016, at 6:32 PM, Robert Widmann via swift-evolution
  wrote:
 
 
> On Jul 21, 2016, at 6:19 PM, Xiaodi Wu  wrote:
> 
> This is nice. Is `areSame()` being proposed because static `==` is
> the status quo and you're trying to make the point that `==` in the
> future need not guarantee the same semantics?
 
 Yep!  Equivalence and equality are strictly very different things.
 
> 
> Nit: I think the more common term in stdlib would be
> `areEquivalent()`. Do you think `same` in that context (independent
> of the word "ordering") might erroneously suggest identity?
 
 There is room for improvement here.  Keep ‘em coming.
 
> 
> 
>> On Thu, Jul 21, 2016 at 8:11 PM, Robert Widmann via
>> swift-evolution
>>  wrote:
>> Hello Swift Community,
>> 
>> Harlan Haskins, Jaden Geller, and I have been working on a
>> proposal to clean up the semantics of ordering relations in the
>> standard library.  We have a draft that you can get as a gist.
>> Any feedback you might have about this proposal helps - though
>> please keeps your comments on Swift-Evolution and not on the gist.
>> 
>> Cheers,
>> 
>> ~Robert Widmann
>> 
>> 
>> 
>> 
>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
> 
 
 ___
 swift-evolution mailing list
 swift-evolution@swift.org
 https://lists.swift.org/mailman/listinfo/swift-evolution
>>> ___
>>> swift-evolution mailing list
>>> swift-evolution@swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>> 
>> 
>> -- 
>> Dave
>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> 
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>

-- 
Dave

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


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Dave Abrahams via swift-evolution

on Fri Jul 22 2016, Tony Allevato  wrote:

> I like a lot of this, but the changes to Equatable are where I get stuck.
> What are the scenarios where areSame is useful *outside* the context of the
> proposed new Comparable interface?
>
> I ask because changing the requirement for Equatable to areSame instead of
> == seems like a backwards change to me. There are plenty of unorderable
> types where == is the obvious thing you want to implement, and this makes
> it less obvious. It also adds a named method to a protocol to serve the
> purpose of an operator, which I've been fighting hard against in SE-0091
> (even though you keep the global one and delegate to it).
>
> There are two concepts at play here: comparability and orderability. 99.99%
> of the time, they are identical. 

The concepts are “domain-specific semantics” vs “semantics that is
useful in generic contexts.”  Yes, they are usually identical.

> Your proposal mentions one place where they're not: IEEE floating
> point numbers, because there exists an element in that space, NaN,
> that doesn't satisfy an equivalence relation at all.  

It's not limited to NaN.  The +0/-0 distinction can be tricky as well.

> But it's still reasonable to want a stable ordering with those
> included.

It's also reasonable to want to search for those in a collection or use
them as hash keys.  I'm pointing this out because it goes to the
definition of equality, which sorting in general does not.

> In the proposal as it's written right now, the individual inequality
> operators are implemented in terms of <=>. That won't work for
> FloatingPoint, because (NaN < x) and (NaN >= x) should both be false but
> the default implementations provided would make the latter true. So
> FloatingPoint would still have to provide its own implementations of *all
> of the (in)equality operators*, not just ==, in order to have the correct
> definition w.r.t. to IEEE 754. I didn't see that called out anywhere in the
> write-up.

That's my error, actually. I wasn't thinking straight when I proposed a
change to the proposal that I claimed dropped the need for the other
operators.

> That being said, don't get me wrong—there's still a lot about this proposal
> that I like :)  Here's what I'm thinking (which is mostly what you have
> written, with some tweaks):
>
> 1) Don't change Equatable. I don't see a need to distinguish between
> equivalence and equality on its own (if there is one, please let me
> know!).

There is, because for algorithms that require Equatable to have any kind
of meaningful semantics the equivalence relation requirement must be
fulfilled, and prominent types exist whose `==` operator is not an
equivalence relation.

> As it stands today, I think the proposal "leaks" ordering concepts into
> Equatable when it shouldn't.

I don't see any evidence for that, and I don't even believe you've said
anything here to support that point of view.

> 2) Comparable defines <=>, as proposed, but *also* defines <, >, <=, >=. A
> protocol extension provides defaults for <, >, <=, >=, ==, and !=
> implemented in terms of <=>. This lets most implementors of Comparable
> implement <=> and get everything else for free, but it also lets types
> replace individual operators with customized implementations (see #4 below)
> easily *within* the type (SE-0091).

Check

> 3) Comparable should be documented to imply that the default behavior is to
> link the behavior of <=> to the individual comparisons, but that it can be
> changed, meaning that only <=> must define a total ordering and the
> individual comparison operators need not.

Yes, the doc comments are missing from the proposal.

> 4) The very few types, like FloatingPoint, that need to provide
> domain-specific behavior to do the obvious/intended thing for users can and
> should override <, >, <=, >=, ==, and !=. This should be called out
> explicitly, and it would *not* affect ordering. 

Depends what you mean by “affect ordering.”  Clearly if you sort Floats
using < explicitly, it will have an effect.

> I think it's entirely reasonable to have (NaN == NaN) return false and
> (NaN != NaN) return true but (NaN <=> NaN) return .same without
> introducing another areSame concept, because the former is demanded by
> IEEE 754.  5) Algorithms that rely on a total order, like sorts, must
> be implemented in terms of <=>, not in terms of the individual
> operators, because of the possibility that the definitions can be
> severed above.

But you're forgetting algorithms that require an equivalence relation,
which is basically everything that's constrained to Equatable.

> As mentioned below, the one thing that a three-way comparison loses is the
> easy ability to pass > instead of < to reverse the ordering, but it's
> trivial to write a function that does this and I think it should be
> included as part of the proposal. Something like this (may be typos, I'm
> writing it in Gmail):
> 
> public func 

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Dave Abrahams via swift-evolution

on Fri Jul 22 2016, Xiaodi Wu  wrote:

> On Fri, Jul 22, 2016 at 2:26 PM, Pyry Jahkola via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> I agree with Tony that we should still keep == and != as part of
>> Equatable, and<, <=, >, and >= as part of Comparable, while offering
>> default implementations through <=>.
>>
>> The reason is, that otherwise generic code would dispatch differently
>> depending on the generic constraint;  would only see the
>> operators using <=> while  would pick up the IEEE-754
>> versions, even if in both cases T were Double.
>>
>> Below is a concrete example where things wouldn't work as expected, given
>> the proposal omitting the other operators in the protocols:
>>
>> Dave Abrahams wrote:
>>
>> >> In order to have an opinion on whether or not this is justified, I
>> >> need to know more about how areSame() may differ from == and how this
>> >> will affect generic code. What is required that could not fit inside
>> >> an override of Equatable?
>> >
>> > Floating point types.  You should be able to ask for
>> > arrayOfFloats.firstIndex(of: x) even if there are NaNs in the array (or
>> > x).
>>
>> Given that func firstIndex(of value: T) dispatches on
>> Equatable, it would use Double.areSame(_:_:) instead of the IEEE-754
>> Double.==(_:_:). While that sounds innocuous, it would cause surprising
>> results in the presense of negative zero:
>>
>> [-0.0, 1.0, .nan, 0.0].firstIndex(of: 0.0)
>> //=> 3, not 0
>>
>
> I just assumed that the core team's vision was that this would be addressed
> by a domain-specific floating point `areSame(a: Self, b: Self) -> Bool {
> return (a == 0 && b == 0) || (a <=> b) == .same }`. This is a valid
> equivalence relation afaik.

IEEE-754 specifies a standard equivalence relation that we'd use for
this.

>> which almost definitely isn't what the caller would want. Instead,
>> functions like these should clearly document (or it should be obvious from
>> their semantics) whether they use == and < (etc), or <=> in their
>> implementation. I think that is a reasonable price to pay.
>>
>> Or am I missing something obvious about round pegs and square holes?
>>
>> — Pyry
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>

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


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Dave Abrahams via swift-evolution

on Fri Jul 22 2016, Xiaodi Wu  wrote:

> On Fri, Jul 22, 2016 at 1:05 PM, Dave Abrahams via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>>
>> on Thu Jul 21 2016, Duan  wrote:
>>
>> > Great proposal. I want to second that areSame may mislead user to
>> > think this is about identity.
>> >
>> > I like areEquivalent() but there may be better names.
>>
>> It really *is* about identity as I posted in a previous message.
>
> Correct me if I'm wrong:

Not to put too fine a point on it, but... ;-)

> Identity is an equality relation, and `==` is about just that. 
> By contrast, `areSame()` is to define an *equivalence* relation

The phrase “equality relation” has no commonly-understood formal or
informal meaning AFAIK.

“Identity” is a slightly informal term IIUC, but for any
commonly-understood meaning of that word, the “is identical to” is
*always* an equivalence relation.

> through which, by default, `==` is to be dispatched.
> Since this design specifically
> contemplates scenarios in which certain Equatables will override `==` *not*
> to dispatch through `areSame()`, 

[Since `==` wouldn't be a protocol requirement (except in FloatingPoint),
it's technically shadowing rather than overriding in the general case.
I imagine this detail doesn't matter to your point]

> the latter function evaluates only *equivalence* with respect to an
> arbitrary equivalence relation, not identity.

Saying that areSame is just any old arbitrary equivalence relation,
would complicate the system in undesirable ways.  It's
a bit subtle but I'll try to walk you through the reasoning:

1. We had a choice about whether to document that Comparable requires
   that <=> be a total order or a strict weak order [A strict weak order
   is a total order over equivalence classes of elements that aren't
   ordered with respect to other members of the same class].  Either one
   will work for the standard algorithms.

2. Because the concept of total order is more accessible and requiring
   <=> to be a total order doesn't seem to reduce expressivity, we
   decided on a total order.

3. The only difference between these two orderings is that in a total
   order the equivalence classes have only a single element, **which
   means that the equivalence relation in play has to, in some sense,
   tell you whether two things are identical**.  This all comes down to
   how you measure “are a and b the same element?”

The alternative is to say that <=> is just a strict weak ordering and
areSame is just any arbitrary equivalence relation, but that really
complicates everything (not just the definition of Comparable).  For
example, you can't document `a.firstIndex(of: b)` as the first index where
`b` appears in `a`; you have to say it's the first index of an element
that satisfies `{ Element.areSame($0, b) }`.

> Put another way, the future `Equatable` is a contract that conforming
> types will supply a definition of equality *and* an equivalence
> relation, where the former by default is dispatched through the
> latter; but it is specifically envisioned that the two may be
> separated in domain-specific scenarios.

That is correct.  However, the equivalence relation in question still
is, in some very real sense, an identity check.

>> But
>> that doesn't change the fact that areEquivalent might be a better name.
>> It's one of the things we considered; it just seemed long for no real
>> benefit.
>>
>> > Daniel Duan
>> > Sent from my iPhone
>> >
>> >> On Jul 21, 2016, at 6:32 PM, Robert Widmann via swift-evolution
>> >>  wrote:
>> >>
>> >>
>> >>> On Jul 21, 2016, at 6:19 PM, Xiaodi Wu  wrote:
>> >>>
>> >>> This is nice. Is `areSame()` being proposed because static `==` is
>> >>> the status quo and you're trying to make the point that `==` in the
>> >>> future need not guarantee the same semantics?
>> >>
>> >> Yep!  Equivalence and equality are strictly very different things.
>> >>
>> >>>
>> >>> Nit: I think the more common term in stdlib would be
>> >>> `areEquivalent()`. Do you think `same` in that context (independent
>> >>> of the word "ordering") might erroneously suggest identity?
>> >>
>> >> There is room for improvement here.  Keep ‘em coming.
>> >>
>> >>>
>> >>>
>>  On Thu, Jul 21, 2016 at 8:11 PM, Robert Widmann via
>>  swift-evolution
>>   wrote:
>>  Hello Swift Community,
>> 
>>  Harlan Haskins, Jaden Geller, and I have been working on a
>>  proposal to clean up the semantics of ordering relations in the
>>  standard library.  We have a draft that you can get as a gist.
>>  Any feedback you might have about this proposal helps - though
>>  please keeps your comments on Swift-Evolution and not on the gist.
>> 
>>  Cheers,
>> 
>>  ~Robert Widmann
>> 
>> 
>> 
>> 
>> 
>>  ___
>>  swift-evolution mailing list

Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Daniel Duan via swift-evolution

> On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution 
>  wrote:
> 
> 
> on Thu Jul 21 2016, Duan  > wrote:
> 
>> Great proposal. I want to second that areSame may mislead user to
>> think this is about identity.
>> 
>> I like areEquivalent() but there may be better names.
> 
> It really *is* about identity as I posted in a previous message.  But
> that doesn't change the fact that areEquivalent might be a better name.
> It's one of the things we considered; it just seemed long for no real
> benefit.
> 

If the addresses of the arguments aren’t being used, then we don’t consider
them part of their *identity*. I can follow this logic. My fear is most users
won’t make this leap on their own and get the same initial impression as I did.
It's entirely possible this fear is unfounded. Some educated bikesheding
wouldn't hurt here IMO :)


>> Daniel Duan
>> Sent from my iPhone
>> 
>>> On Jul 21, 2016, at 6:32 PM, Robert Widmann via swift-evolution
>>>  wrote:
>>> 
>>> 
 On Jul 21, 2016, at 6:19 PM, Xiaodi Wu  wrote:
 
 This is nice. Is `areSame()` being proposed because static `==` is
 the status quo and you're trying to make the point that `==` in the
 future need not guarantee the same semantics?
>>> 
>>> Yep!  Equivalence and equality are strictly very different things.
>>> 
 
 Nit: I think the more common term in stdlib would be
 `areEquivalent()`. Do you think `same` in that context (independent
 of the word "ordering") might erroneously suggest identity?
>>> 
>>> There is room for improvement here.  Keep ‘em coming.
>>> 
 
 
> On Thu, Jul 21, 2016 at 8:11 PM, Robert Widmann via
> swift-evolution
>  wrote:
> Hello Swift Community,
> 
> Harlan Haskins, Jaden Geller, and I have been working on a
> proposal to clean up the semantics of ordering relations in the
> standard library.  We have a draft that you can get as a gist.
> Any feedback you might have about this proposal helps - though
> please keeps your comments on Swift-Evolution and not on the gist.
> 
> Cheers,
> 
> ~Robert Widmann
> 
> 
> 
> 
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
 
>>> 
>>> ___
>>> swift-evolution mailing list
>>> swift-evolution@swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
> 
> -- 
> Dave
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org 
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Pyry Jahkola via swift-evolution
Xiaodi Wu wrote:

> I just assumed that the core team's vision was that this would be addressed 
> by a domain-specific floating point `areSame(a: Self, b: Self) -> Bool { 
> return (a == 0 && b == 0) || (a <=> b) == .same }`. This is a valid 
> equivalence relation afaik.

I guess so, but it's a different from what Dmitri gave here:

>> 7. What, in fact, is the proposed total order for the stdlib's 
>> floating-point types?
> 
> The IEEE 754 definition.
> 
> https://github.com/apple/swift/blob/f318fe853d7898246db24d501f1ddc03c9eb8651/stdlib/public/core/FloatingPoint.swift.gyb#L855

— Pyry

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


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Dave Abrahams via swift-evolution

on Fri Jul 22 2016, Matthew Johnson  wrote:

>> On Jul 22, 2016, at 9:48 AM, Karl via swift-evolution 
>>  wrote:
>> 
>> 
>>> On 22 Jul 2016, at 03:32, Robert Widmann via swift-evolution
>>> 
>>> >
>>> wrote:
>>> 
>>> 
 On Jul 21, 2016, at 6:19 PM, Xiaodi Wu
 > wrote:
 
 This is nice. Is `areSame()` being proposed because static `==` is
 the status quo and you're trying to make the point that `==` in
 the future need not guarantee the same semantics?
>>> 
>>> Yep!  Equivalence and equality are strictly very different things.
>>> 
>> 
>> As I understand it:
>> 
>> -> what we call “Equatable” today checks for equivalence. For value
>> types, equivalent is the same as equality (that’s why they are
>> values - two instances with the same data are indistinguishable).
>> -> For reference types, we have an instance-equality operator (===)
>> which checks for what I believe you mean by equality.
>
> Except that the standard floating point == is not an equivalence
> relation.  I’m not sure if the distinction introduced by this proposal
> is solely due to that or if there are other example use cases for
> making a distinction.

Floating point is just the most common/important example.  Different
domains (see posets for a random example
https://en.wikipedia.org/wiki/Partially_ordered_set) attach different
semantics to the standard mathematical comparison operators = ≠ < ≤ > ≥,
which in programming we traditionally write as ==, !=, <, <=, >, >=.

The points of this proposal are:

1. To decouple the meanings of these operators from the semantics
   required for generic algorithms to work (thus making it possible to
   use floating point in generic contexts).

2. Secondarily, to avoid dropping efficiency on the floor in compound
   comparisons.

>> 
>> Karl
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>

-- 
Dave

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


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Dave Abrahams via swift-evolution

on Thu Jul 21 2016, Xiaodi Wu  wrote:

> On Thu, Jul 21, 2016 at 10:23 PM, Jose Cheyo Jimenez via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>>
>>
>> On Jul 21, 2016, at 7:15 PM, Duan via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> Great proposal. I want to second that areSame may mislead user to think
>> this is about identity.
>>
>> I like areEquivalent() but there may be better names.
>>
>>
>> what about areEqual() ?
>>
>
> As Robert mentioned above, the point here is explicitly to distinguish
> equivalence from equality.

Which suggests maybe we should rename the protocol.

>>
>>
>> Daniel Duan
>> Sent from my iPhone
>>
>> On Jul 21, 2016, at 6:32 PM, Robert Widmann via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>
>> On Jul 21, 2016, at 6:19 PM, Xiaodi Wu  wrote:
>>
>> This is nice. Is `areSame()` being proposed because static `==` is the
>> status quo and you're trying to make the point that `==` in the future need
>> not guarantee the same semantics?
>>
>>
>> Yep!  Equivalence and equality are strictly very different things.
>>
>>
>> Nit: I think the more common term in stdlib would be `areEquivalent()`. Do
>> you think `same` in that context (independent of the word "ordering") might
>> erroneously suggest identity?
>>
>>
>> There is room for improvement here.  Keep ‘em coming.
>>
>>
>>
>> On Thu, Jul 21, 2016 at 8:11 PM, Robert Widmann via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>> Hello Swift Community,
>>>
>>> Harlan Haskins, Jaden Geller, and I have been working on a proposal to
>>> clean up the semantics of ordering relations in the standard library.  We
>>> have a draft that you can get as a gist.
>>>   Any
>>> feedback you might have about this proposal helps - though please keeps
>>> your comments on Swift-Evolution and not on the gist.
>>>
>>> Cheers,
>>>
>>> ~Robert Widmann
>>>
>>>
>>>
>>>
>>>
>>> ___
>>> swift-evolution mailing list
>>> swift-evolution@swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>
>>>
>>
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>

-- 
Dave

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


Re: [swift-evolution] [Draft][Proposal] Formalized Ordering

2016-07-22 Thread Dave Abrahams via swift-evolution

on Thu Jul 21 2016, Duan  wrote:

> Great proposal. I want to second that areSame may mislead user to
> think this is about identity.
>
> I like areEquivalent() but there may be better names.

It really *is* about identity as I posted in a previous message.  But
that doesn't change the fact that areEquivalent might be a better name.
It's one of the things we considered; it just seemed long for no real
benefit.

> Daniel Duan
> Sent from my iPhone
>
>> On Jul 21, 2016, at 6:32 PM, Robert Widmann via swift-evolution
>>  wrote:
>> 
>> 
>>> On Jul 21, 2016, at 6:19 PM, Xiaodi Wu  wrote:
>>> 
>>> This is nice. Is `areSame()` being proposed because static `==` is
>>> the status quo and you're trying to make the point that `==` in the
>>> future need not guarantee the same semantics?
>> 
>> Yep!  Equivalence and equality are strictly very different things.
>> 
>>> 
>>> Nit: I think the more common term in stdlib would be
>>> `areEquivalent()`. Do you think `same` in that context (independent
>>> of the word "ordering") might erroneously suggest identity?
>> 
>> There is room for improvement here.  Keep ‘em coming.
>> 
>>> 
>>> 
 On Thu, Jul 21, 2016 at 8:11 PM, Robert Widmann via
 swift-evolution
  wrote:
 Hello Swift Community,
 
 Harlan Haskins, Jaden Geller, and I have been working on a
 proposal to clean up the semantics of ordering relations in the
 standard library.  We have a draft that you can get as a gist.
 Any feedback you might have about this proposal helps - though
 please keeps your comments on Swift-Evolution and not on the gist.
 
 Cheers,
 
 ~Robert Widmann
 
 
 
 
 
 ___
 swift-evolution mailing list
 swift-evolution@swift.org
 https://lists.swift.org/mailman/listinfo/swift-evolution
 
>>> 
>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>

-- 
Dave

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


  1   2   >