- Draft here: swift-evolution/XXXX-unwrappable.md at unwrappable · erica/swift-evolution · GitHub
- Previous discussions:
Introducing an Unwrappable
protocol
- Proposal: SE-TBD
- Author(s): Chris Lattner, Erica Sadun
- Review manager: TBD
- Status: Not implemented
Introduction
This proposal introduces an Unwrappable
protocol, which introduces Optional-like behavior for any biased wrapped type. It extends Optional sugar to any associated-type enumeration.
Swift-evolution thread:
TBD
Motivation
Optional magic should not be limited to the Optional
type. So long as an enumeration is biased towards a positive case (in Optional
, that is .some
), they should be able to conform to an Unwrappable
protocol and inherit the features that power optional sugar in the Swift language.
Unwrappable
will allow the compiler to move unwrapping from its internals into the standard library. This allows Swift to simplify compiler implementation and unify its optional-specific behaviors (including chaining, nil-coalescing (??
), if let
/guard let
, forced unwraps (!), etc) so they can be repurposed for additional types.
An Unwrappable
protocol instead of a single generic enum or struct (as with Optional
) supports more complex cases, greater overall flexibility, and better reach to other types that can take advantage of unwrapping features.
For example, a Result
type conforming to Unwrappable
could use already-existing constructs to process success
cases:
enum Result: Unwrappable { ... }
if let value = result {
// use the value from Result's `.success(T)` case
}
Detailed Design
Conforming type define an Element
associated type, and provide an unwrap
method that attempts to extract that value from any enum case:
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
or value
case in a (yet to be designed) result type, e.g. enum Result<T, E> { case success(T), other(E) }
. Adopting Unwrappable
enables conforming types to inherit many behaviors currently limited to optionals.
Conforming Result
to Unwrappable
enables users 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 other
. 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
. Should a boilerplate enum property proposal be accepted, you could produce code along these lines:
if let value = result {
// use result
} else {
if let error = result.fail.value {
throw error
}
Fatal.unreachable("Should never get here") // Dave DeLong's Fatal umbrella type
}
Impact on Existing Code
This proposal will largely impact the compiler instead of end-users, who should not notice any changes outside of new standard library features.
Source compatibility
This proposal is strictly additive.
Effect on ABI stability
This proposal does not affect ABI stability.
Effect on API resilience
This proposal does not affect ABI resilience.
Alternatives Considered
Not adopting this proposal