Funções genéricas do operador personalizado: um caso curioso de uma instrução incorreta *

Eu me deparei com esse problema enquanto brincava com operadores genéricos e personalizados no Swift. No trecho de código abaixo, estou introduzindo dois novos operadores de prefixo, ∑ e ∏, e implemento suas funções de prefixo como soma vetorial e produto, respectivamente. Para não precisar implementar essas e outras funções semelhantes para todos os tipos de números inteiros e de ponto flutuante separadamente, defini dois protocolos: Summable (que requer + implementação) e Multiplicável (que requer * implementação). Além disso, implementei as duas funções dos argumentos SequenceType, que funcionam, por exemplo, com os tipos Array e Rage. Finalmente, você pode ver pelas chamadas println no final do snippet que tudo isso funciona muito bem, exceto por ∏ (1 ... 100). Aqui, o programa trava com EXC_BAD_INSTRUCTION e não há muito mais o que continuar. Observe que ∑ (1 ... 100) funciona, mesmo que seja implementado da mesma maneira. De fato, se eu alterar o valor inicial na linhareturn reduce(s, 1, {$0 * $1}) a 0 do que o programa é concluído sem erros, embora com saídas incorretas das chamadas para ∏.

Então, tudo se resume a usar 0 ou 1 como valor inicial !? Quando o código na linha incorreta é descompactado em várias linhas, fica claro que a falha ocorre em$0 * $1. Observe também que, em vez dos fechamentos{$0 * $1} e{$0 + $1} Eu deveria poder passar as funções de operador + e * diretamente. Infelizmente, isso ofende o compilador: "A aplicação parcial do método genérico não é permitida".

Alguma ideia? Como a troca de 1 (ou qualquer Int diferente de zero) por 0 pode causar uma falha? E por que isso acontece apenas com intervalos para multiplicação, enquanto intervalos para adição com 0 ou 1 valores iniciais funcionam bem?

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

Edição: Embora um pouco embaraçoso para mim, o erro que estou cometendo neste código faz um teste bonito dos seus olhos de programação. Veja se consegue descobrir antes de ler a resposta de Martin abaixo. Você se sentirá bem consigo mesmo quando o fizer. (No entanto, talvez seja necessário procurar outra carreira.)

questionAnswers(1)

yourAnswerToTheQuestion