Can't change func({closure}) => func {closure} in guard statement

Normally, when passing a closure as the only argument in a function call, you can move the closure outside the argument list and then discard the empty argument list. However, using Xcode 11.4.1, in this code

    init?(id: String) {
        guard id.allSatisfy { $0.isASCII } else {return nil }

I get the error messages

Cannot convert value of type '((String.Element) throws -> Bool) throws -> Bool' (aka '((Character) throws -> Bool) throws -> Bool') to expected condition type 'Bool'

Expected 'else' after 'guard' condition

Anonymous closure argument not contained in a closure

If I put parentheses around the closure, turning it back into an ordinary argument, the compiler is happy.

Is this some language restriction I'm not familiar with?

The issue is that Swift thinks your { $0.isASCII } needs an else before it. When using closures with conditional statements, you must wrap them in the parentheses otherwise the parser (I believe) will fail. This below code should work

init?(id: String) {
    guard id.allSatisfy({$0.isASCII }) else { return nil }

You will need to do this wrapping inside while conditions, and if conditions as well.

You could also use key path expressions as function syntax

init?(id: String) {
    guard id.allSatisfy(\.isASCII) else { return nil }
1 Like

OK, I suppose that makes sense. It’s just a minor inconvenience. Thanks.