2014-06-10 16 views
10

Sto provando a scrivere un'estensione per l'esempio Matrix dal libro, slightly tweaked to be generic.
Sto provando a scrivere un metodo chiamato getRow che restituisce una sequenza di valori nella riga specificata.Come si restituisce una sequenza in Swift?

In C#, avrei scritto questo:

IEnumerable<T> GetRow (int row) 
{ 
    return Enumerable 
     .Range (0, this.columns) 
     .Select ((column) => this.grid[row, columns]); 
} 

o in alternativa

IEnumerable<T> GetRow (int row) 
{ 
    for (var column = 0; column < this.columns; column++) { 
     yield return this.grid[row, column]; 
    } 
} 

Non sono sicuro di come fare questo a Swift però.

Sequence sembra essere l'equivalente di IEnumerable<T>, ma non capisco il motivo per cui utilizza typealias invece di essere definita come Sequence<T> (see also this). Definizione di un metodo che restituisce generico Sequence<T> non ha funzionato:

extension Matrix { 
    // Cannot specialize non-generic type 'Sequence' 
    func getRow<T>(index: Int) -> Sequence<T> { 
     return map(0..self.columns, { self[index, $0] }) 
    } 
} 

Poi mi sono liberato di <T> (ma come si suppone che sia generica?):

extension Matrix { 
    func getRow(index: Int) -> Sequence { 
     return map(0..self.columns, { self[index, $0] }) 
    } 
} 

Questo compila! Tuttavia non posso usarlo:

var row = grid.getRow(0) 
// 'Sequence' does not conform to protocol '_Sequence_' 
for i in row { 
    println("\(i)") 
} 

Come faccio correttamente digitare map risultato in modo che possa essere consumato in un ciclo for..in?

più su questo tema: Associated Type Considered Weird

risposta

9

Joe Groff suggested per avvolgere il risultato in SequenceOf<T>:

extension Matrix { 
    func getRow(index: Int) -> SequenceOf<T> { 
     return SequenceOf(map(0..self.columns, { self[index, $0] })) 
    } 
} 

In effetti, questo funziona, ma abbiamo dovuto avvolgere map risultato in una classe di supporto, che differisce da come lo faccio in C#.

devo ammettere che non capisco ancora perché Sequence e Generator uso typealias e non sono protocolli generici (come IEnumerable<T> in C#).C'è una interessante discussione in corso su questa distinzione quindi lascio alcuni link per una mente curiosa:

  1. Associated Types Considered Weird
  2. Associated types vs. type parameters - reason for the former?
  3. Abstract Type Members versus Generic Type Parameters in Scala
  4. Generics and protocols
+0

Grazie per tutti questi link - molto apprezzato. – ColinE

+0

Non dimenticare che SequenceOf è stato rimosso dalle versioni recenti di Swift. –

1

Penso che tu sia in fase di indurre in errore dal compilatore Swift (che è un po 'traballante per il momento). Il tipo per il tuo intervallo 0..self.columns è Range<Int>, che non è un Sequence o Collection, quindi non penso che possa essere utilizzato tramite map.

L'implementazione funziona per me:

extension Matrix { 
    func getRow(index: Int) -> T[] { 
    var row = T[]() 
    for col in 0..self.columns { 
     row.append(self[index, col]) 
    } 
    return row 
    } 
} 
+0

io FILE un radar ... Come faccio a mantenere la sequenza pigra? –

+0

@Dan sono pigri? Se eseguo una mappa su un array ma non faccio nulla con i risultati, la chiusura viene comunque eseguita per tutti i valori dell'array. – ColinE

+0

Strano! Ho pensato che, se non restituisce un array, allora deve essere pigro. Lo controllerò. –

Problemi correlati