2014-10-02 1 views
1

Может ли кто-нибудь увидеть свет на эту ошибку? Игровая площадка настаивает на том, что аргумент № 2 отсутствует, но нет аргумента # 1!Swift: Отсутствует аргумент в вызове безразмерного расширения SequenceOf

Цель кода подсчитать количество прогонов условного значения и вернуть последовательность кортежей, состоящую из значений и их счетчиков. Я много работал над этим кодом, оптимизируя его и дорабатывая, пока не уверен, что он должен работать ... но хотя он компилируется, я не могу назвать его так, как он был предназначен.

Ошибки я получаю от вызова кода ниже missing argument for parameter #2 in call

extension SequenceOf { 
    func CountRuns<T: Equatable>() -> SequenceOf<(T, Int)> { 
     return SequenceOf<(T, Int)>([]) 
     return SequenceOf<(T, Int)> {() -> GeneratorOf<(T, Int)> in 
      var generator = self.generate() 
      var previousValue: T? 
      var start = true 
      return GeneratorOf<(T, Int)> {() -> (T, Int)? in 
       var count = 1 
       var retValue: (T, Int)? 
       while(true) { 
        var value = generator.next() as T? 
        if start { 
         previousValue = value 
         start = false 
        } else if value != nil && value! == previousValue! { 
         count++ 
        } else { 
         if previousValue != nil { 
          retValue = (previousValue!, count) 
         } 
         previousValue = value 
         break 
        } 
       } 
       return retValue 
      } 
     } 
    } 
} 

println(SequenceOf(y).CountRuns()) 

Playground execution failed: <EXPR>:327:23: error: missing argument for parameter #2 in call 
println(SequenceOf(y).CountRuns()) 
        ^

ответ

1

Проблемы у Вас есть то, что вы не можете на самом деле расширить общий тип с методом, который далее специализируется его родовое подтип. То есть ваш метод countRuns требует, чтобы общий подтип T был Equatable, но вы можете предоставить эти ограничения только в первоначальном объявлении типа, а не в расширении.

Решение состоит в том, чтобы объявить countRuns как функцию верхнего уровня, например, так:

func countRuns<T: Equatable>(s: SequenceOf<T>) -> SequenceOf<(T, Int)> { 
    return SequenceOf<(T, Int)> {() -> GeneratorOf<(T, Int)> in 

     // note the change from self.generate() to s.generate() here 
     var generator = s.generate() 

     var previousValue: T? 
     var start = true 
     return GeneratorOf<(T, Int)> {() -> (T, Int)? in 
      var count = 1 
      var retValue: (T, Int)? 
      while(true) { 
       var value = generator.next() as T? 
       if start { 
        previousValue = value 
        start = false 
       } else if value != nil && value! == previousValue! { 
        count++ 
       } else { 
        if previousValue != nil { 
         retValue = (previousValue!, count) 
        } 
        previousValue = value 
        break 
       } 
      } 
      return retValue 
     } 
    } 
} 

println(countRuns(SequenceOf(y))) 

Это было покрыто (немного) в конце this NSHipster article.

+0

Хм ... это работает. Не то, что я хочу, хотя, как я хочу сделать цепочку. –

0

Я нашел лучший ответ! Спасибо Нейту за то, что поставили меня на правильный путь.

Хитрость заключается в том, что компаратор должен поступать с верхнего уровня, где определяется тип. Итак, окончательное решение имеет только три изменения: во второй строке, шестнадцатой строке и в вызове. Изменение заключается в передаче компаратора и использовании компаратора вместо прямой компиляции значений.

extension SequenceOf { 
    func CountRuns(areEqual: (T, T) -> Bool) -> SequenceOf<(T, Int)> { 
     return SequenceOf<(T, Int)>([]) 
     return SequenceOf<(T, Int)> {() -> GeneratorOf<(T, Int)> in 
      var generator = self.generate() 
      var previousValue: T? 
      var start = true 
      return GeneratorOf<(T, Int)> {() -> (T, Int)? in 
       var count = 1 
       var retValue: (T, Int)? 
       while(true) { 
        var value = generator.next() as T? 
        if start { 
         previousValue = value 
         start = false 
        } else if value != nil && areEqual(value!, previousValue!) { 
         count++ 
        } else { 
         if previousValue != nil { 
          retValue = (previousValue!, count) 
         } 
         previousValue = value 
         break 
        } 
       } 
       return retValue 
      } 
     } 
    } 
} 

let y = [0, 0, 0, 2, 2, 2, 3, 4 ,4, 5, 65, 65] 
println(SequenceOf(y).CountRuns(==).ToArray()) 
let z = [0.0, 0.0, 0.0, 2.0, 2.0, 2.0, 3.0, 4.0, 4.0, 5.0, 65.0, 65.0] 
println(SequenceOf(z).CountRuns(==).ToArray()) 

// Prints: 
// [(0, 3), (2, 3), (3, 1), (4, 2), (5, 1), (65, 2)] 
// [(0.0, 3), (2.0, 3), (3.0, 1), (4.0, 2), (5.0, 1), (65.0, 2)] 

Это значит, что это общее решение проблемы общего эквивалентного протокола.