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.