问题
I have come across (most definitely) a feature that I don't quite understand. I have a closure, that takes in a Float
and has no return value, aka (number: Float) -> Void
. In that closure, I perform a call on optional value, not forcing its unwrapping, because I like the behavior since the optional is a delegate (= if it's nil, don't do anything).
But when I do that, I get an error:
Cannot convert the expression's type '...' to type Float.
Interestingly enough, when I simply add println()
, the error disappears. I have simplified my case to tiny little example for illustration:
var optional: [String : Int]?
let closure: (number: Int) -> Void = { (number) -> Void in
optional?.updateValue(number, forKey: "key")
//println() <-- when this gets uncommented, error disappears
}
My bet would be that the compiler maybe doesn't like that in some cases I'm not handling the float number, but since I am not returning the value then it should just disappear right? What am I missing?
回答1:
An expression containing a single expression is inferred to return that result, hence:
let closure: (number: Int) -> Void = { (number) -> Void in
optional?.updateValue(number, forKey: "key")
}
is equivalent to:
let closure: (number: Int) -> Void = { (number) -> Void in
return optional?.updateValue(number, forKey: "key")
}
You now have conflicting return types between Void
and Int?
(remember, updateValue
returns the old value)
Splitting it up with an explicit return clarifies the inferred typing.
let closure: (number: Int) -> Void = { (number) -> Void in
optional?.updateValue(number, forKey: "key")
return
}
回答2:
I think your closure won't like returning nil because Void can't be converted to nil.
If you do that in a playground:
var n: Void = ()
n = nil
You'll get this error: error: type 'Void' does not conform to protocol 'NilLiteralConvertible'
来源:https://stackoverflow.com/questions/28882441/cannot-convert-the-expressions-type-with-optional-in-closure-body