10

Ich versuche, eine Reihe von Bool s zu reduzieren, indem den logischen Operator Anwendung OR (||) mit dem folgenden Code, jedoch bekomme ich einen Fehler:Verwendung logischer Operator als kombiniert Verschluss reduzieren

func reduceBools(values: [Bool]) -> Bool { 
    return values.reduce(false, combine: ||) 
} 

Ambiguous reference to member '||'

Analog für Ganzzahlen funktioniert der Code wie ein Charme.

func reduceInts(values: [Int]) -> Int { 
    return values.reduce(0, combine: +) 
} 

konnte ich es durch Zugabe einer || Funktion (Code unten) oder mit einem { $0 || $1 } Verschluss, aber ich mag nicht diese Ansätze machen zu arbeiten, und ich würde einfach den Bediener vorbei bevorzugen.

func ||(lhs: Bool, rhs: Bool) -> Bool { 
    return lhs || rhs 
} 

Das gleiche geschieht für den logischen UND (&&) Operator.

Wie kann ich es ohne den oben genannten Hack machen?

+3

funktionieren wird, dass eine Wanze/Einschränkung aufgrund der "autoclosure" Parameter '||' und '' && zu sein scheint. Vergleichen Sie http://stackoverflow.com/questions/28648268/what-is-the-type-of-the-logical-operators und die folgenden Kommentare. –

+0

@MartinR danke für den Link! Ich dachte, dass ich nur ein dummer Mann bin ... – user3441734

+0

@MartinR das scheint der Fall zu sein:/Gibt es irgendeinen Rdar darauf, damit ich es dupen kann? – fpg1503

Antwort

15

Als Alternative können Sie den folgenden Ansatz verwenden

// || 
func reduceBoolsOr(values: [Bool]) -> Bool { 
    return values.contains(true) 
} 

// && 
func reduceBoolsAnd(values: [Bool]) -> Bool { 
    return !values.contains(false) 
} 

Beachten Sie, dass .reducecomes with an overhead. Wenn die Endergebnis ist die Bedeutung Ihrer Frage (anstatt über das unerwartete Verhalten von || und && Betreiber in diesem Zusammenhang zu fragen), dann vielleicht der pragmatische Ansatz oben kann hilfreich sein, auch wenn es nicht wirklich reduziert Array, jedoch aufgrund der einfachen Natur des booleschen Typs das gleiche Ergebnis liefern.

+1

Ich würde argumentieren, dass die Verwendung von enthält in diesem Fall noch besser ist, weil Sie das gewünschte Ergebnis beschreiben um zu bekommen, anstatt wie man es berechnet. Es ist noch deklarativer als der übliche funktionale Ansatz. :) –

1

Unklarer Verweis auf Mitglied '||' bedeutet, dass es mehrere mögliche Kandidaten gibt, aus denen der Compiler nicht auswählen kann. In Ihrem Fall sind solche

public func ||<T : BooleanType, U : BooleanType>(lhs: T, @autoclosure rhs:() throws -> U) rethrows -> Bool 

und

public func ||<T : BooleanType>(lhs: T, @autoclosure rhs:() throws -> Bool) rethrows -> Bool 

wahrscheinlich die 'Hack' mit einem { $0 || $1 } ist die beste Lösung hier.

+0

Es sieht so aus, als ob der einzige Grund für den zweiten darin liegt, dass der erste wegen eines Fehlers nicht '@ _transparent' sein kann. Das Verrückteste ist, dass ihre Implementierungen identisch sind. – fpg1503

0

Dies geschieht wegen Swifts Schließung Semantik. Es nimmt Ihre Argumente und wendet Funktion auf sie an, Argumentnamen auslassend.

protocol Numeric { 
    ... 
    public static func +(lhs: Self, rhs: Self) -> Self 
    ... 
} 

Im Beispiel mit Ints, würden Sie (Int, Int) in einen Verschluss und + Funktion in Numeric-Protokoll erwartet genau zwei Ints sie zusammenzufassen passieren.

Das ist, warum Code wie unten ganz gut funktioniert

[1, 2, 3, 4].reduce(0, +) 

Weil Sie nur 2 Ints nahm und angewandte Funktion, die nur zwei Ints nimmt. Wenn Sie Ihre eigene Funktion schreiben, die nur zwei Argumente benötigt, würde es auch funktionieren.

func myOwnAwesomeFunc<T: Numeric>(a: T, b: T) -> T { in 
    return 1 // production ready 
} 

[1, 2, 3, 4].reduce(0, myOwnAwesomeFunc) // prints 1 

Gut so weit.Aber warum können wir nicht schreiben

[true, false, true].reduce(false, ||) // yields Cannot invoke 'reduce' 
// with an argument list of type 
// '(Bool, (Bool, @autoclosure() throws -> Bool) throws -> Bool)' 

Das ist, weil dieser Operator bool und eine Schließung nimmt, die bool zurückgibt. Nicht Bool, Verschluss! Aber wenn es so ist, warum schreiben wir nicht true || { false }()? Das liegt an @autoclosure, die sich um geschweifte Klammern für uns kümmert.

Haupt Frage, warum ist es auf diese Weise implementiert, so dass wir Swifts super kurze short-hand Closure-Syntax mit booleans verwenden können? IDK

-1

Nach Ansatz

values.reduce(false) { $0 || $1 } 
Verwandte Themen