Why is the shorthand argument name $0 returning a tuple of all parameters?
I was trying to define a variable that can hold a closure and ran into some difficulties using Swift's shorthand argument names. Take the following code snippet:
var returnAString: (String, String) -> String
returnAString = { return $0 }
This gives me the compile error '(String, String)' is not convertible to 'String'. When I modify the closure return a string with the first argument value, I get back both argument values in a tuple.
println(returnAString("1", "2")) // Prints "(1, 2)"
However, if I modify the closure to print the second argument the correct argument is printed as expected.
returnAString = { $1 }
println(returnAString("1", "2")) // Prints "2"
I've got the feeling that I'm doing something a little silly here, but I couldn't find any explanation of why this would be happening.
Closures § Shorthand Argument Names
Shorthand Argument Names
… the number and type of the shorthand argument names will be inferred from the expected function type.
It looks like this is the expected behavior. By providing only $0
you are inferring (at least to the system) that you want a tuple.
This only seems to be a special case of using $0
. For example, the following cannot be compiled.
var returnAString3: (String, String, String) -> String
returnAString3 = { return $1 }
No matter how it's modified.
returnAString3 = { return $1.0 } // still fails.
Type inferral is treating $0
as a tuple instead of the first argument, because you are not using the 2nd parameter.
If you just reference the 2nd parameter instead it works correctly:
returnAString = { $1; return $0 }
A proof that what I am saying is correct comes from 0x7fffffff's comment:
returnAString = { $0.0 }
which means take the first value of the $0
tuple and return it.