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 
> <swift-evolution@swift.org> wrote:
> 
> 
>> On Apr 25, 2017, at 5:25 PM, Xiaodi Wu <xiaodi...@gmail.com 
>> <mailto:xiaodi...@gmail.com>> wrote:
>> 
>> On Tue, Apr 25, 2017 at 6:53 PM, Jonathan Hull <jh...@gbis.com 
>> <mailto:jh...@gbis.com>> 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 <xiaodi...@gmail.com 
>>> <mailto:xiaodi...@gmail.com>> wrote:
>>> 
>>> On Sun, Apr 16, 2017 at 1:14 PM, Jonathan Hull <jh...@gbis.com 
>>> <mailto:jh...@gbis.com>> wrote:
>>> 
>>>> On Apr 16, 2017, at 10:42 AM, Xiaodi Wu via swift-evolution 
>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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
> 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

Reply via email to