I'm broadly +0.5 on this proposal—I support the addition of the move
functionality at a high level but I remain apprehensive about a couple items that I raised in the pitch: namely, move(_:)
as a function specifically and the lack of @discardableResult
and/or drop
.
The proposal introduces move
as the following:
The
move
function consumes a movable binding, which is either an unescaped locallet
, unescaped localvar
, or function argument, with no property wrappers or get/set/read/modify/etc. accessors applied.
but IMO this is glossed over far too quickly—the concept of a "function which consumes a movable binding" (or indeed, any binding at all) is an entirely new concept, and isn't even representable in Swift today. The purported signature of the move(_:)
function is a bit of a fiction. This is discussed and justified in Alternatives considered:
Declaring
move
as a function also minimizes the potential impact to the language syntax. We've introduced new contextual keywords without breaking compatibility before, likesome
andany
for types. But to do so, we've had to impose constraints on their use, such as not allowing the constraints modified bysome
orany
to be parenthesized to avoid the result looking like a function call. Although that would be acceptable formove
given its current constraints, it might be premature to assume we won't expand the capabilities ofmove
to include more expression forms.
AFAICT, though, this really only rebuts the proposed spelling of move x
and not the other alternatives discussed just above such as #move(x)
or @move x
. In a vacuum it strikes me as equally premature to assume that move
will expand to include more expression forms—the expansions discussed in Future directions still only really cover expansions of the potential bindings we could apply this function to.
As written the proposal doesn't convince me that move(_:)
will ever be able to be "just another function"—not even the Ownership roadmap lays out such a scheme. If it were the plan of record that we'd be adding ownership features until move(_:)
could be a function that anyone could write, I'd be a lot more on board with this direction, but since that's not the case I can't really get past the feeling that move
-as-a-function isn't appropriate for Swift. There are too many limitations and special cases for not enough gain, IMO.
It's not really enough to hinder my overall support for the proposal, but I think that in its current form it will become a part of the language that we will forever have to caveat as "yes, I know it looks like a function but it's better not to think of move(_:)
like a Swift function at all because X, Y, Z."
My second objection is less pressing since it could be rectified in a backwards-compatible manner, but I still think it would be nice to address as part of the initial proposal.
I also want to reiterate my thoughts on the lack of @discardableResult
in this proposal, which is discussed as part of the rejection of the drop
function:
We could also introduce a separate
drop
function like languages like Rust does that doesn't have a result likemove
does. We decided not to go with this since in Swift the idiomatic way to throw away a value is to assign to_
implying that the idiomatic way to writedrop
would be:_ = move(x)
suggesting adding an additional API would not be idiomatic. We do not propose making
move
use the@discardableResult
attribute, so that this kind of standalone drop is syntactically explicit in client code.
This reasoning still strikes me as somewhat backwards (in the formal sense). The way I see it is that using @discardableResult
is the idiomatic way to design an API for which one of the expected uses is to discard the result. If that's the case for move(_:)
then we should have move(_:)
be tagged as @discardableResult
. If we're worried that a bare move(x)
is somehow not explicit enough (see below), that's justification for a drop
function.
The idiomatic way to throw a value away is to assign to _
only in cases where the API designer does not consider discarding the result a 'supported' use case of the API—it doesn't make sense to me to design an API where we 'support` the drop functionality by forcing users to use discard assignment.
I also have this lingering related question from the pitch: