- Proposal: TBD
- Author: TBD
- Status: TBD
- Review manager: TBD
This proposal introduces an Unwrappable
protocol and the supporting technology that allows associated-type enumerations to support unwrapping beyond the Optional
type.
Swift-evolution thread: TBD
Optional magic should not be limited to the Optional
type. Removing unwrapping support from the compiler into the standard library will allow Swift to simplify compiler details and unify its optional-specific behaviors like chaining, nil coalescing (??
), if let
, forced unwrap (!
), etc, enabling their repurposing for additional types as well as optionals.
Using a protocol for Unwrappable
instead of a single generic enum or struct (as with Optional
) supports more complex cases and greater overall flexibility.
This protocol design allows a conforming type to unwrap a single associated value type.
protocol Unwrappable {
associatedtype Element
func unwrap() -> Element?
}
Unwrappable
types declare their preference for a single unwrapped type like the some
case for Optional
and the success
case in a (yet to be designed) result type, e.g. enum Result<T> { case success(T), failure(Error) }
. Adopting Unwrappable
allows conforming types to inherit many behaviors currently limited to optionals.
Conforming Result
to Unwrappable
would enable you to introduce if let
binding and functional chaining that checks for and succeeds with a success
case (type T
) but otherwise discards and ignores errors associated with failure
(conforming to Error
). Unwrappable
allows you to shortcut, coalesce, and unwrap-to-bind as you would an Optional
, as there's always a single favored type to prefer.
Unwrappable
enables code to ignore and discard an error associated with failure
, just as you would when applying try?
to convert a thrown value to an optional. The same mechanics to apply to Optional
would apply to Result
including features like optional chaining, forced unwrapping and so forth.
The design of Unwrappable
should allow an unpreferred error case to throw on demand and there should be an easy way to convert a throwing closure to a Result
.
// Any throwing call or block can become a `Result`:
let myResult = Result(of: try myThrowingCall())
// Later (this could even be in a different thread)
let value = try unwrap myResult // throws on `failure`
This proposal will largely impact the compiler instead of end-users, who should not notice any changes outside of new standard library features.
Not adopting this proposal