I\'m trying to understand how does it work:
1> func returnNone() -> String? { return .None }
2> returnNone() == nil
$R0: Bool = true
3> ret
enum Optional
conforms to the NilLiteralConvertible
protocol,
which means that it can be initialized with the "nil" literal.
The result is Optional<T>.None
where the type placeholder T
must be inferred from the context.
As an example,
let n = nil // type of expression is ambiguous without more context
does not compile, but
let n : Int? = nil
does, and the result is Optional<Int>.None
.
Now optionals can in general not be compared 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 the operator
public func ==<T>(lhs: T?, rhs: _OptionalNilComparisonType) -> Bool
where _OptionalNilComparisonType
is not documented officially.
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 the comparison of any optional type with "nil", regardless of whether the underlying type is Equatable
or not.
In short – in the context of Optional
– nil
can be thought of as a shortcut to .None
, but the concrete type must be inferred from the context. There is a dedicated ==
operator for comparison with "nil".