Alternatively, we could introduce a new type `PotentiallyUnknown` that’s kind
of like `Optional` but has different equality semantics. We’d probably also
need to introduce a `PartiallyEquatable` (probably the wrong word) protocol too
though. I don’t think this is really that feasible.
protocol PartiallyEquatable {
static func ==(lhs: Self, rhs: Self) -> Bool?
}
enum PotentiallyUnknown<T: PartiallyEquatable> {
case known(T)
case unknown(T)
}
extension PotentiallyUnknown: PartiallyEquatable when T: PartiallyEquatable {
static func ==(lhs: PotentiallyUnknown, rhs: PotentiallyUnknown) -> Bool? {
guard case .known(let l) = lhs, case .known(let r) = rhs else {
return nil
}
return l == r
}
}
I think it’s a novel idea, but I don’t think it would work great in practice.
> On Apr 25, 2017, at 6:38 PM, Jonathan Hull via swift-evolution
> <[email protected]> wrote:
>
>
>> On Apr 25, 2017, at 5:25 PM, Xiaodi Wu <[email protected]
>> <mailto:[email protected]>> wrote:
>>
>> On Tue, Apr 25, 2017 at 6:53 PM, Jonathan Hull <[email protected]
>> <mailto:[email protected]>> wrote:
>> I just wanted to ask for more detail on why this is a non-starter (it seems
>> like most of my ideas are dismissed as “non-starters”, but I am rarely given
>> a detailed reason why).
>>
>> Migration would be a renaming from ‘Double' to ‘Double?’, but it wouldn’t be
>> cosmetic. It would free us to use a non-optional Double, where we can
>> guarantee the answer wouldn’t be NaN/nil. We would, as you say, have
>> functions like ‘cos(Double?)->Double?’ which propagate the optional, but we
>> could also add a ‘cos(Double)->Double’ overload which guarantees an actual
>> result. For something like Tan, we would only have the optional version
>> because the answer may actually be undefined, even when the input isn't.
>>
>> Leave aside how one might implement such a system for a moment. The first
>> major issue is that your idea does not address the issues we're talking
>> about here:
>>
>> We are debating, for instance, how to compare arrays with elements of type
>> `Double`. In your design, the question remains how we would compare arrays
>> with elements of type `Double?`. If the answer is that you cannot compare
>> arrays of type `[Double?]`, then we have a problem, because that's the type
>> that people will use when they ingest data that might contain NaN. Sure,
>> they can unwrap each element before using their data, but they can also test
>> each element with `isNaN` today. We are trying to *improve* on the user
>> experience of comparing arrays of floating point values *without* checking
>> if they contain NaN, not trying to take that feature away.
>
> It solves the main problem we are dealing with in Comparable because defining
> Comparable on non-optional Double (without possibility of NaN) is fairly
> simple.
>
> You could compare an array of ‘Double?' in the same way you could compare an
> array of ‘Int?’ now. It would work the same way optionals work everywhere
> else.
>
> You would just test for a lack of numerical result by checking the optional
> in the usual Swift way: guard let, if let, etc...
>
>
>> Your design also doesn't address the problem of how NaN should compare with
>> NaN. Only now, you've pushed the problem to `Optional`. By design, every
>> `Optional<T>.none` compares equal to every other `Optional<U>.none` (yes,
>> even of different types).
> Yes, the one major difference in behavior, which I mentioned in my earlier
> email, is that we are replacing NaN != NaN with nil == nil. Everything else
> should behave the same. The part that saves us here, is that Swift forces
> you to explicitly consider the optional case.
>
> Basically, I am taking the spirit/intent of the law over the letter of it.
> As far as I can tell, (quiet) NaN was originally designed to provide the
> functionality which we use optional for in Swift. The NaN != NaN thing came
> out of limitations of the computers in the 1980’s because you needed a way to
> tell if something was NaN or not (and isNaN() didn’t exist yet).
>
> The programmer (mental) model would be that Swift Double just doesn’t have
> NaN, and anywhere where you would normally return NaN, you return nil
> instead. However, the property of using NaN’s bits to represent nil let’s us
> inter-op seamlessly with C and ObjC (or any other language’s) code. They
> just treat it as a double with NaN as normal (including NaN != NaN) and we
> interface with it as ‘Double?'
>
>> This did not always work correctly, if I recall, but it does now and it's an
>> intentional part of the design. However, NaN must compare not equal to every
>> NaN. These could not be more different properties. It seems quite absurd on
>> its face that we might want NaN to compare equal to a value of type
>> `Optional<UIViewController>`.
>
> Is there an algorithm that requires NaN != NaN that couldn’t be reasonably
> rewritten to handle nil/optionals instead?
>
> I haven’t been able to think of one. They are extremely similar, because they
> were designed for the same use-cases. The examples you have given so far
> (e.g. cos(Double)->Double) would all be trivial to migrate.
>
> Thanks,
> Jon
>
>
>>
>>
>> In short, it would actually make people consider conditions which result in
>> NaN because of Swift’s machinery which makes people consider nil.
>>
>> It also allows non-optional Double to easily conform to Comparable, and
>> removes the gotchas around Collections… Pretty big wins for a “cosmetic
>> rename”. The only thing we lose is 'NaN != Nan' (because nil == nil), but
>> then algorithms that had relied on that would be forced to consider the
>> NaN/nil case explicitly because of the optionals.
>>
>> It would also inter-op well with C/ObjC code by just having the compiler
>> overlay Double? for Double…
>>
>> Thanks,
>> Jon
>>
>>
>>> On Apr 16, 2017, at 11:44 AM, Xiaodi Wu <[email protected]
>>> <mailto:[email protected]>> wrote:
>>>
>>> On Sun, Apr 16, 2017 at 1:14 PM, Jonathan Hull <[email protected]
>>> <mailto:[email protected]>> wrote:
>>>
>>>> On Apr 16, 2017, at 10:42 AM, Xiaodi Wu via swift-evolution
>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>
>>>> The point is that, when you manipulate two real numbers, sometimes there
>>>> is no numeric result. You cannot simply wish this away with a new numeric
>>>> type because it is not an artifact of _modeling_ real numbers but rather
>>>> intrinsic to mathematics itself.
>>>
>>> I agree with the rest of what you said, but I have to disagree on this
>>> point. What I think he is saying is that, in Swift, we really should be
>>> representing the NaN case as an optional instead of a magic value on the
>>> type itself (similar to how swift uses an optional instead of NSNotFound).
>>>
>>> In fact, that might be an actual option here. For ‘Double?’ the compiler
>>> could use the bit pattern for NaN internally to represent .none (I believe
>>> it does similar tricks to save space with other optional types). Then
>>> disallow reference to NaN within swift code. Functions or operations which
>>> could produce NaN would either have to produce an optional or trap in case
>>> of NaN. (e.g. the trig functions would likely return an optional, and 0/0
>>> would trap).
>>>
>>> I think it would actually lead to much better code because the compiler
>>> would force you to have to explicitly deal with the case of optional/NaN
>>> when it is possible. Migration would be tricky though...
>>>
>>> This is essentially a cosmetic renaming from `Double` to `Double?`. There
>>> are rules for propagating NaN which numeric algorithms expect. For example,
>>> `cos(.nan)` returns a value. If your design is to work, every function that
>>> takes a `Double` will need to take a `Double?`.
>>>
>>> Just as Swift String conforms to Unicode standards, FloatingPoint conforms
>>> to IEEE standards. You'd have to come up with enormous benefits to justify
>>> breaking that. Doing so for Swift 4 is plainly a non-starter.
>>>
>>> Thanks,
>>> Jon
>>
>>
>
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution