Swift Optional Type: how. None == nil works

I am trying to understand how this works:

1> func returnNone() -> String? { return .None } 2> returnNone() == nil $R0: Bool = true 3> returnNone() == .None $R1: Bool = true 

Why .None is nil .

I see nothing about this in the enum definition:

 public enum Optional<Wrapped> : _Reflectable, NilLiteralConvertible { case None case Some(Wrapped) /// Construct a `nil` instance. public init() /// Construct a non-`nil` instance that stores `some`. public init(_ some: Wrapped) /// If `self == nil`, returns `nil`. Otherwise, returns `f(self!)`. @warn_unused_result @rethrows public func map<U>(@noescape f: (Wrapped) throws -> U) rethrows -> U? /// Returns `nil` if `self` is nil, `f(self!)` otherwise. @warn_unused_result @rethrows public func flatMap<U>(@noescape f: (Wrapped) throws -> U?) rethrows -> U? /// Create an instance initialized with `nil`. public init(nilLiteral: ()) } 
+5
source share
1 answer

enum Optional conforms to the NilLiteralConvertible protocol, which means that it can be initialized with the literal "nil". The result is Optional<T>.None , where a placeholder of type T should be inferred from the context.

As an example,

 let n = nil // type of expression is ambiguous without more context 

not compiled but

 let n : Int? = nil 

and the result is Optional<Int>.None .

Now optional parameters cannot be compared at all if the underlying type is not Equatable :

 struct ABC { } let a1 : ABC? = ABC() let a2 : ABC? = ABC() if a1 == a2 { } // binary operator '==' cannot be applied to two 'ABC?' operands 

and even this does not compile:

 if a1 == Optional<ABC>.None { } // binary operator '==' cannot be applied to two 'ABC?' operands 

But this compiles:

 if a1 == nil { } 

It uses an operator

 public func ==<T>(lhs: T?, rhs: _OptionalNilComparisonType) -> Bool 

where _OptionalNilComparisonType is not officially documented. In https://github.com/andelf/Defines-Swift/blob/master/Swift.swift the definition can be found as (found by @rintaro and @Arsen, see comments):

 struct _OptionalNilComparisonType : NilLiteralConvertible { init(nilLiteral: ()) } 

This allows you to compare any optional type with "nil", regardless of whether the base type is Equatable or not.

In short - in the context of Optional - nil can be seen as a shortcut to .None , but the specific type should be inferred from the context. For comparison with "nil", there is a dedicated == operator.

+12
source

Source: https://habr.com/ru/post/1234008/


All Articles