The advent of the special syntactic form consume
has rendered all three of swap
, exchange
and Optional.take
entirely redundant, as these functions are all "trivial" helpers consisting of a few consume
invocations.
func swap<T: ~Copyable>(_ a: inout T, _ b: inout T) {
let temp = consume a
a = consume b
b = consume temp
}
func exchange<T: ~Copyable>(
_ item: inout T,
with newValue: consuming T
) -> T {
let oldValue = consume item
item = consume newValue
return oldValue
}
extension Optional where Wrapped: ~Copyable {
mutating func take() -> Self {
let result = consume self
self = nil
return result
}
}
These functions do not contribute anything that we wouldn't otherwise be able to express. From a strict, soulless technical standpoint, these are all completely redundant. This does not make these functions outliers, though -- the majority of preexisting functionality in the Standard Library is also redundant in this sense. For example, your favorite notational examples if foo == nil
and foo = nil
are also entirely redundant, as one could "simply" choose to spell them if case .none = foo
and foo = .none
, respectively.
However, this does not at all mean that these features are "unnecessary". Quite the opposite! These APIs give proper names to frequently occurring patterns: they establish a vocabulary for Swift developers, freeing them from the need to repeatedly puzzle out the underlying simple intention.
The Standard Library going out of its way to implement these redundant notations (and SE-0437 taking pains to make sure they carry over to this new age of noncopyable types) is not at all a waste -- it gives the language its expressivity and character. It is crucial that we provide a great selection of utility operations: these helpers are lubricants for the gears of coding.
Optional.take()
gives a name to a frequently needed operation. take
is not just a good name for this function -- it is a great one! Not only does it capture exactly what this operation does, but it does so in a wonderfully succinct manner that flows great in code. As an additional bonus, it matches the terminology used by our friendly competitor / role model Rust.
As John explained, take
does not introduce the idea of a type with an "implicit default value" -- Optional
has had an implicit default nil
value since the start.
The page has now turned on this proposal. The review period is over; the changes have landed, and work has now progressed to building new things on top of them. If we discover a major issue with what was proposed, we may of course need to revisit it. This is, however, not the right time to start bikeshedding accepted API additions -- there is a huge amount of work that SE-0437 has left undone, and for the language to progress, we need to look forward, not back.