`_ = withAnimation { ... }` vs. `let _ = withAnimation { ... }`: both work, what's the difference?

Both work:

if list[0].isInvalid {
    _ = withAnimation { list.removeFirst() }
}
if list[0].isInvalid {
    let _ = withAnimation { list.removeFirst() }
}

why the first case let can be omitted?

Would be nicer, since removeFirst() is @discardableResult, if Swift can make withAnimation(...) also @discardableResult

withAnimation is part of the Apple Core Graphics frameworks, which is actually written in Objective-C with a Swift API. Private frameworks. Open-source Swift team cannot make change, although some of the Apple members of the team also work the private Apple side. You can make an enhancement request using Feedback Assistant or at the Apple bug reporting site.

1 Like

Both "ignore" forms come from "destructuring" syntax:

let pair = (1, 2)

let (x, y) = pair
let (_, y) = pair // only binds y

var x, y: Int
(x, y) = pair
(_, y) = pair // only modifies y

So both syntaxes are valid. You could say the short one means "set nothing to this" and the one with let means "initialize nothing with this", but they both have the same effect and will always compile to "just release this value".


While withAnimation alone isn't going to change any time soon, it seems reasonable that methods of the form foo<T>(callback: () -> T) -> T could allow the result to be discardable if the value passed for callback has a discardable result. Then again, maybe that's not always the desired behavior, so this would probably need actual discussion of the desired behavior, whether it should be explicitly annotated on the declaration of foo, etc.


Personally I would write this one as

withAnimation {
  _ = list.removeFirst()
}

rather than

_ = withAnimation {
  list.removeFirst()
}

just so the value never gets out of the closure to begin with. As far as the run-time behavior goes it's "just" a micro-optimization, but I think it's clearer to read as well.

6 Likes

Given

@discardableResult
func foo<T>(_ arg: T) → Any { ... }

… I'd like for elements.forEach(foo) to compile.

That is, I'd like @discardableResult functions to be usable where a Void-returning function is expected.

I believe that already works even when it’s not @discarableResult, but if it doesn’t I agree that would be a good indicator.

Sadly, it seems that even with the @discardableResult it gives a "cannot convert" error.

1 Like