组合多个Bool返回值而不会短路

时间:2016-06-28 19:52:01

标签: objective-c swift bitwise-and

Swift 2限制了对Bool值使用按位运算符。这是令人愉快的。在ObjC中,当您需要执行每个操作数时使用它非常有用。例如:

a.isFoo() & b.isFoo() & c.isFoo()

在这种情况下,使用按位& 将执行每个方法。

如果我使用逻辑运算符&& ,它将执行第一个运算符,如果为false,表达式将返回false而不执行其他两个操作数。

我希望找到与& 一样优雅的方式,在Swift中使用Bool。有可能吗?

3 个答案:

答案 0 :(得分:6)

你在Objective-C中所做的并不是优雅的"。这很邋and,你不应该这样做。如果你想调用三种方法,只需调用这三种方法!但是形成一个布尔表达式,你应该使用逻辑运算符,而不是按位运算符。所以,例如:

let (ok1, ok2, ok3) = (a.isBool(), b.isBool(), c.isBool())
let ok = ok1 && ok2 && ok3

答案 1 :(得分:2)

没有这样的特殊操作员,但我可能会这样做:

if ![a.isBool(), b.isBool(), c.isBool()].contains(false) {

或只是

let aCondition = a.isBool()
let bCondition = b.isBool()
let cCondition = c.isBool()

if aCondition && bCondition && cCondition {

但您也可以为此定义自己的运算符。

答案 2 :(得分:2)

您可以在方法调用数组上使用reduce操作来模仿相同的行为,例如。

/* example setup */
struct Foo {
    let bar: Bool
    init(_ bar: Bool) { self.bar = bar }

    func isTrue() -> Bool { print("\(bar) foo!"); return bar }
}

let a = Foo(false)
let b = Foo(false)
let c = Foo(true)

/* naturally all three method calls will execute to construct the boolean
   array, whereafter reduce will evaluate the combined conditional statement */ 
if [a.isTrue(), b.isTrue(), c.isTrue()].reduce(true, combine: { $0 && $1 }) {
    print("Reached this ...")
} /* false foo!
     false foo!
     true foo! */

let d = Foo(true)
let e = Foo(true)
let f = Foo(true)

if [d.isTrue(), e.isTrue(), f.isTrue()].reduce(true, combine: { $0 && $1 }) {
    print("Reached this ...")
} /* true foo!
     true foo!
     true foo!
     Reached this ... */

或者例如将方法作为可变参数提供给执行方法执行的函数并组合条件

func foo(calls: (() -> Bool)...) -> Bool {
    return calls.map{ $0() }.reduce(true, combine: { $0 && $1})
}

let a = Foo(false)
let b = Foo(false)
let c = Foo(true)

if foo(a.isTrue, b.isTrue, c.isTrue) {
    print("Reached this ...")
} /* false foo!
     false foo!
     true foo! */

let d = Foo(true)
let e = Foo(true)
let f = Foo(true)

if foo(d.isTrue, e.isTrue, f.isTrue) {
    print("Reached this ...")
} /* true foo!
     true foo!
     true foo!
     Reached this ... */