组合多个 Bool return 值而不短路

Combining multiple Bool return values without shortcircuiting

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

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

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

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

我想找到与 & 相同的优雅方式,在 Swift 中使用 Bool。可能吗?

您在 Objective-C 中所做的不是 "elegant"。这很卑鄙,你不应该这样做。如果你想调用三个方法,就调用那三个方法!但是形成一个布尔表达式,你应该使用逻辑运算符,而不是位运算符。所以,例如:

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

没有这样的特殊运算符,但我可能会这样做:

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 {

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

您可以使用对方法调用数组的 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: { [=10=] &&  }) {
    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: { [=10=] &&  }) {
    print("Reached this ...")
} /* true foo!
     true foo!
     true foo!
     Reached this ... */

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

的函数
func foo(calls: (() -> Bool)...) -> Bool {
    return calls.map{ [=11=]() }.reduce(true, combine: { [=11=] && })
}

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 ... */
let values = [a.isFoo(), b.isFoo(), c.isFoo()]
let result = values.allSatisfy { [=10=] }