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