быстрые ленивые последовательности - почему компилятор жалуется, когда введено определение - PullRequest
1 голос
/ 17 января 2020

Я работаю с Lazy Sequence of Ints:

let a = [1,2,3].lazy

Я начинаю с определения потока Ints следующим образом:

protocol Stream: LazySequenceProtocol where Element == Int {}
extension LazySequence:       Stream  where Element == Int {}
extension LazyMapSequence:    Stream  where Element == Int {}

Я буду делать сложные вещи с потоки, но чтобы продемонстрировать проблему, я буду держать вещи простыми. Я расширяю поток, чтобы разрешить увеличивающиеся значения:

extension Stream {
  func increment() -> some Stream {
    map{ value in
      return value + 1
    }
  }
}
print(Array(a.increment())) // Prints [2, 3, 4]

Обратите внимание, что a.increment () - это ленивая функция, поэтому ее необходимо заключить в Array (), чтобы превратить результаты в массив для печати. .

Также обратите внимание на использование слова "some", которое было введено в Swift 5.1 для представления непрозрачного типа и позволяет нам реализовывать потоки таким образом - без непрозрачных типов это не так. так просто.

И я могу сделать более интересные вещи, такие как вставка 10-кратного значения после себя:

extension Stream {
  func insert10x() -> some Stream {
    flatMap{ value in
      return [value, value*10]
    }
  }
}
print(Array(a.insert10x()))             // Prints [1, 10, 2, 20, 3, 30]

И это означает, что я могу начать составлять свои функции в разных способы:

print(Array(a.insert10x().increment())) // Prints [2, 11, 3, 21, 4, 31]
print(Array(a.increment().insert10x())) // Prints [2, 20, 3, 30, 4, 40]

Все вышеперечисленное компилируется и работает как положено.

НО ... Если я введу дополнительную строку, такую ​​как "let multiplier = 10" ниже, то получу компилятор ошибки:

extension Stream {
  func insert10xVersion2() -> some Stream {
    flatMap{ value in                      // Error 1
      let multiplier = 10
      return [value, value * multiplier]   // Error 2
    }
  }
}
print(Array(a.insert10xVersion2()))             // Should prints [1, 10, 2, 20, 3, 30]

Две ошибки компилятора:

Ошибка 1: «flatMap» устарела: пожалуйста, используйте compactMap (_ :) для случая, когда Закрытие возвращает необязательное значение. Вместо этого используйте 'compactMap (_ :).

Ошибка 2: Невозможно преобразовать возвращаемое выражение типа' [Int] 'в тип возвращаемого значения' Int? '

Кажется, что обе ошибки указывают на то, что компилятор решил, что flatMap имеет дело с дополнительными функциями, поэтому поощряет использование взамен CompactMap.

Но я бы подумал, что это должно дать идентичные результаты для первого версия!

Возможно, это ошибка компилятора, но я подумал, что сначала я проверю здесь, чтобы узнать, может ли кто-нибудь увидеть проблему с моим кодом?

...