Allgemeine benutzerdefinierte Operatorfunktionen: Ein merkwürdiger Fall einer schlechten * Anweisung

Ich stoße auf dieses Problem, während ich mit allgemeinen und benutzerdefinierten Operatoren in Swift spiele. Im folgenden Codeausschnitt stelle ich zwei neue Präfixoperatoren vor, ∑ und ∏, und implementiere dann ihre Präfixfunktionen als Vektorsumme bzw. Produkt. Um diese und ähnliche Funktionen nicht für alle Integer- und Floating-Point-Typen separat implementieren zu müssen, habe ich stattdessen zwei Protokolle definiert: Summable (für die + Implementierung erforderlich ist) und Multiplicable (für die * Implementierung erforderlich ist). Außerdem habe ich die beiden Funktionen für SequenceType-Argumente implementiert, die beispielsweise mit Array- und Rage-Typen funktionieren. Schließlich können Sie an den println-Aufrufen am Ende des Snippets erkennen, dass dies bis auf ∏ (1 ... 100) ganz gut funktioniert. Hier stürzt das Programm mit EXC_BAD_INSTRUCTION ab und es bleibt nicht viel anderes zu tun. Beachten Sie, dass ∑ (1 ... 100) funktioniert, obwohl es auf die gleiche Weise implementiert ist. Tatsächlich, wenn ich den Anfangswert in der Zeile @ ändereturn reduce(s, 1, {$0 * $1}) bis 0, wenn das Programm fehlerfrei abgeschlossen wird, jedoch mit falschen Ausgaben von Aufrufen an ∏.

So läuft alles darauf hinaus, 0 oder 1 als Anfangswert zu verwenden !? Wenn der Code in der fehlerhaften Zeile über mehrere Zeilen entpackt wird, wird deutlich, dass der Absturz bei @ auftrit$0 * $1. Beachten Sie auch, dass anstelle der Verschlüsse{$0 * $1} und{$0 + $1} Ich sollte in der Lage sein, die Operatorfunktionen + und * direkt zu übergeben. Leider beleidigt dies den Compiler: "Eine teilweise Anwendung der generischen Methode ist nicht erlaubt".

Irgendwelche Ideen? Wie kann das Vertauschen von 1 (oder einer anderen Int) gegen 0 zu einem Absturz führen? Und warum passiert das nur mit Bereichen für die Multiplikation, während Bereiche für die Addition mit entweder 0 oder 1 Anfangswerten gut funktionieren?

prefix operator ∑ {}
prefix operator ∏ {}

protocol Summable { func +(lhs: Self, rhs: Self) -> Self }
protocol Multiplicable { func *(lhs: Self, rhs: Self) -> Self }

extension Int: Summable, Multiplicable {}
extension Double: Summable, Multiplicable {}

prefix func ∑<T, S: SequenceType where T == S.Generator.Element, 
    T: protocol<IntegerLiteralConvertible, Summable>>(var s: S) -> T {
    return reduce(s, 0, {$0 + $1})
}

prefix func ∏<T, S: SequenceType where T == S.Generator.Element, 
    T: protocol<IntegerLiteralConvertible, Multiplicable>>(var s: S) -> T {
    return reduce(s, 1, {$0 * $1})
}

let ints = [1, 2, 3, 4]
let doubles: [Double] = [1, 2, 3, 4]

println("∑ints = \( ∑ints )") // --> ∑ints = 10
println("∑doubles = \( ∑doubles )") // --> ∑doubles = 10.0
println("∑(1...100) = \( ∑(1...100) )") // --> ∑(1...100) = 5050

println("∏ints = \( ∏ints )") // --> ∏ints = 24
println("∏doubles = \( ∏doubles )") // --> ∏doubles = 24.0
println("∏(1...100) = \( ∏(1...100) )") // --> CRASH: EXC_BAD_INSTRUCTION

EDIT: Der Fehler, den ich in diesem Code mache, ist für mich zwar etwas peinlich, aber ein netter Test für Ihr Programmierauge. Sehen Sie nach, ob Sie es herausfinden können, bevor Sie Martins Antwort unten lesen. Du wirst dich gut fühlen, wenn du es tust. (Möglicherweise muss ich jedoch eine andere Karriere suchen.)

Antworten auf die Frage(1)

Ihre Antwort auf die Frage