There obviously has to be a way to AND or OR multiple booleans.
I'm getting this error trying to write a function like this...
func isLocationWithinView(location: CGPoint, view: UIView) {
// return (location.x >= CGRectGetMinX(view.frame)) && (location.x <= CGRectGetMaxX(view.frame)) && (location.y >= CGRectGetMinY(view.frame)) && (location.y <= CGRectGetMaxY(view.frame))
var a = true
var b = false
return a && b // Error: Binary operator '&&' cannot be applied to two 'Bool' operands
}
What's the solution to this?
The error is misleading: the core is that you're missing return type ... -> Bool
in your function signature, hence attempting to assign a boolean value to the empty tuple type ()
(with no explicit return type, the function expects returns to be of empty tuple type ()
).
You can reproduce this misleading error for any attempt to assign a boolean value to a non-boolean type, where the boolean value is a result of a logical AND/OR expression being performed in the same expression as the invalid assignment:
var a : () = (true && false) /* same error */
var b : Int = (true && false) /* same error */
var c : () = (true || false) /* same error (for binary op. '||') */
Whereas if you wrap your AND/OR operations in a closure or simply assign them to an intermediate boolean variable, you loose the obfuscated error message and is presented with the actual error.
var d : () = { _ -> Bool in return (true && false) }()
/* Cannot convert call result type 'Bool' to expected type '()' */
var e = true && false
var f : () = e
/* Cannot convert value of type 'Bool' to expected type '()' */
Now as to why you're given this misleading error. Both logical operators &&
and ||
are implemented with a conditional evaluation of their right hand side expressions (rhs
), so that the rhs
can be lazily evaluated only in case the left hand side (lhs
) evaluates to true
/false
for &&
/||
operators, respectively.
/* e.g. the AND '&&' logical binary infix operator */
func &&(lhs: BooleanType, @autoclosure rhs: () -> BooleanType) -> Bool {
return lhs.boolValue ? rhs().boolValue : false
}
Since the lhs
itself is invalid for the assignment that follows, possibly the lazy closure rhs
throws an error incurred by the "external" invalid assignment from Bool
type to ()
, but the error thrown ("Binary op '&&
' cannot be applied ...") is not the actual source of the failure of &&
call.
To verify, we can implement our own non-lazy AND operator, say &&&
, and, as expected, we don't receive the same obfuscate error:
infix operator &&& {
associativity right
precedence 120
}
func &&&(lhs: BooleanType, rhs: BooleanType) -> Bool {
return lhs.boolValue ? rhs.boolValue : false
}
var g : () = false &&& true
/* Cannot convert value of type 'Bool' to expected type '()' */
While the other answer has some really interesting points, in this particular case, adding a return type to your function solves it.
func isLocationWithinView(location: CGPoint, view: UIView) -> Bool {
let a = true
let b = false
return a && b // Error: Binary operator '&&' cannot be applied to two 'Bool' operands
}
This would return true
if a
were true, and if not, it would look to b
(lazy evaluation).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With