2014-06-10 12 views
10

Próbuję zapisać rozszerzenie dla przykładu Matrix z książki, slightly tweaked to be generic. Próbuję napisać metodę o nazwie getRow, która zwraca ciąg wartości w danym wierszu.Jak mogę zwrócić sekwencję w Swift?

W języku C#, bym napisał tak:

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

lub alternatywnie

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

Nie jestem pewien, jak to zrobić w Swift chociaż.

Sequence wydaje się być równoważne IEnumerable<T> ale nie rozumiem, dlaczego używa typealias zamiast po prostu jest zdefiniowany jako Sequence<T> (see also this). Definiowanie metodę, która zwraca rodzajowe Sequence<T> nie działa:

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

Potem pozbyła <T> (ale jak to się ma być generic):

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

kompiluje to! Jednak nie mogę go używać:

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

Jak poprawnie wpisać map rezultat dzięki czemu może być spożywany w for..in pętli?

Więcej na ten temat: Associated Type Considered Weird

Odpowiedz

9

Joe groffa suggested zawinąć wynik w SequenceOf<T>:

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

Rzeczywiście, to działa, ale musieliśmy zawijać map rezultat do klasy pomocnika, który różni się od tego, jak to robię w C#.

muszę przyznać, że jeszcze nie rozumiem, dlaczego Sequence i Generator użycie typealias i nie są protokoły generyczne (jak IEnumerable<T> w C#).Jest to interesująca trwa dyskusja o tym rozróżnieniu więc będę zostawić kilka linków ciekawy pamiętać:

  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

Dziękuję za wszystkie te linki - bardzo doceniane. – ColinE

+0

Nie zapomnij, że SequenceOf został usunięty z ostatnich wersji Swift. –

1

myślę, że są w błąd przez Swift kompilatora (który jest nieco łuszcząca się w tej chwili). Typ dla zakresu 0..self.columns to Range<Int>, który nie jest Sequence ani Collection, więc nie sądzę, aby można go było użyć przez map.

Realizacja działa dla mnie:

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

będę złożyć radar ... Jak jednak zachować leniwą sekwencję? –

+0

@ Czy oni są leniwi? Jeśli wykonuję mapę w tablicy, ale nic nie robię z wynikami, zamknięcie jest nadal wykonywane dla wszystkich wartości tablicy. – ColinE

+0

Weird! Myślałem, że jeśli nie zwróci tablicy, to musi być leniwy. Sprawdzę to. –

Powiązane problemy