Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Suppressing Implicit Returns in Swift

Tags:

swift

Consider the following set of functions:

func testFunc(someFunc: (Int[]) -> ()) {
    someFunc([1, 2, 3])
}

func someFunc<T>(arr : T[]) -> T[] {
    return arr
}

func someOtherFunc<T>(arr : T[]) {
    println(arr)
}

// case 1 - ERROR
testFunc() {
    someFunc($0)
}

// case 2 - no error
testFunc() {
    println("whatever")
    someFunc($0)
}

// case 3 - no error
testFunc() {
    someOtherFunc($0)
}

It looks like in case 1, Swift is trying to implicitly return from the closure since the function someFunc() returns a value. It only does this if there is only one line in the closure (Implicit Returns from Single-Expression Closures) - this is why case 2 works. It does not do this if the function, as in case 3 is Void, i.e. it doesn't return a value.

My question is whether there is a way to suppress this behavior so that I can have a function with a return value as a single-line expression in a closure that has no return value.

like image 556
Cezary Wojcik Avatar asked Jun 05 '14 21:06

Cezary Wojcik


1 Answers

Besides the mentioned solutions:

testFunc { someFunc($0); return () } // returning Void explicitly (with or without parenthesis)

testFunc { someFunc($0); 42 } // or, indeed, just adding a second expression

You can also consume the returned value:

testFunc { let x = someFunc($0) }

or simply:

testFunc { _ = someFunc($0) }

Returned value must always be of the type promised by the function signature, and the case of the implicit return is no different. This is no bug. It is simply that the implicit returns are so often such elegant syntax that the less frequent case of the mismatching types is breaking the spell a bit. This is not to say that a nice syntactic solution would not be welcomed, at least when Void is expected. Perhaps something as simple as:

testFunc { someFunc($0) ; } // with the trailing semicolon

When this irritates me the most is when my own function forces me to dance around it. I have a couple of times resorted to explicitly ignoring the return type:

func testFunc<Ignored>(someFunc: [Int] -> Ignored) {
    someFunc([1, 2, 3])
}

testFunc { someFunc($0) }
like image 108
Milos Avatar answered Sep 29 '22 21:09

Milos