dasblinkenlight dasblinkenlight - 6 months ago 8
Swift Question

Can I make a class that participates in "if let" constructs the way the Optional does?

I can use

if let
construct to unwrap optionals, like this:

if let x = someOptional {
// x represents the value of someOptional, and is known to be non-nil
}


In addition to doing the unwrapping, Swift compiler knows to treat the
let x = someOptional
construct as a logical value.

Is the logic for
Optional
built into the compiler itself, or is it possible to define my own class with the same behavior?

In other words, can I write something like this:

class MyLogical : SomeProtocolForSwiftToKnowHowToTreatMyClassAsBool {
...
var boolValue : Bool {
return ... // true or false, depending on the state of my object
}
}


and have Swift treat it like a logical value that I can put inside an
if
condition, with or without
let
?

if let x = getMyLogical() {
assert(x.boolValue) // boolValue must evaluate to true to get here
}


Note: I remember there being a
LogicalValue
protocol in an earlier version of Swift, and
Optional
used to conform to that protocol.
LogicalValue
is gone now, and there is no replacement (
BooleanType
has the
boolValue
property now, but Apple discourages conformance to the
BooleanType
protocol unless your class represents a simple Boolean value).

Answer

Swift's powerful pattern matching system makes something close to this very possible. The case let... pattern does much of what you propose:

if case let x = getMyLogical() where x.boolValue {
    assert(x.boolValue) // boolValue must evaluate to true to get here
}

It works with guard statements too:

guard case let x = getMyLogical() where x.boolValue else { fatalError() }

assert(x.boolValue) // boolValue must evaluate to true to get here

In other words, the case let... syntax can be used to conditionally bind any value to any name for use in an if block or after a guard statement.

Comments