Reputation: 2382
I have the following curried function and I received an Xcode warning that Curried function syntax will be removed in a future version of Swift; use a single parameter list, but the suggested fix-it didn't work (it simply combined the parameters into one function call). I am trying to convert to the new format, but I don't understand how it works. The beginFetchWithCompletionHandler
function below expects handleDownload
to have the parameter signature of (data : NSData?, error : NSError?)
.
fetcher.beginFetchWithCompletionHandler(handleDownload)
I want to also pass in an integer, as follows:
fetcher.beginFetchWithCompletionHandler(handleDownload(0))
The following curried function works perfectly (but gives the warning):
func handleDownload(iCount : Int)(data : NSData?, error : NSError?) -> Void {
print(iCount)
print(data!.length)
}
Here is what I've tried, but I get the error, "Expression resolves to an unused function":
func handleDownload2(iCount:Int) -> (NSData?, NSError?) -> Void {
return { (data: NSData?, error: NSError?) -> Void in {
// received image
print(iCount)
print(data!.length)
}
}
}
Upvotes: 3
Views: 183
Reputation: 92459
The Swift Evolution proposal SE-0002 - Removing currying func declaration syntax that was accepted states:
We remove support for multiple argument patterns in
func
declarations, reducing the grammar forfunc-signature
to allow only oneargument
clause. For migration purposes, existing code that uses currying declaration syntax can be transformed to explicitly return a closure instead:
// Before:
func curried(x: Int)(y: String) -> Float {
return Float(x) + Float(y)!
}
// After:
func curried(x: Int) -> (String) -> Float {
return {(y: String) -> Float in
return Float(x) + Float(y)!
}
}
Thus, the answer given by Martin R in order to solve your code is correct:
func handleDownload2(iCount: Int) -> (NSData?, NSError?) -> Void {
return { (data: NSData?, error: NSError?) -> Void in
// received image
print(iCount)
print(data!.length)
}
}
Note, however, that you can be more concise:
func handleDownload2(iCount: Int) -> (NSData?, NSError?) -> Void {
return { (data, error) in
// received image
print(iCount)
print(data!.length)
}
}
Here, the type of data
and error
is implicitly given by the return type of your handleDownload2
function: (NSData?, NSError?) -> Void
.
Although I would not recommend it for readability matters, your code can be even more concise by using shorthand argument names:
func handleDownload2(iCount: Int) -> (NSData?, NSError?) -> Void {
return {
// received image
print(iCount)
print($0!.length)
}
}
Furthermore, I sometime try to be explicit when I use closures as it helps me set quickly the correct return type for them:
func handleDownload2(iCount: Int) -> (NSData?, NSError?) -> Void {
let innerBlock: (NSData?, NSError?) -> Void = { (data, error) in
// received image
print(iCount)
print(data!.length)
}
return innerBlock
}
Upvotes: 1
Reputation: 539795
The inner curly braces are wrong, it should be:
func handleDownload2(iCount:Int) -> (NSData?, NSError?) -> Void {
return { (data: NSData?, error: NSError?) -> Void in
// received image
print(iCount)
print(data!.length)
}
}
Upvotes: 2