Тип DictionaryIterator не соответствует протоколу 'Sequence' при возврате DictionaryIterator из класса контейнера - PullRequest
0 голосов
/ 07 марта 2020

В этом коде компилятор Swift жалуется на вторую итерацию с использованием возвращенного значения DictionaryIterator:

import Foundation

class Container
{
    private var mArray: [String] = ["One", "Two", "Three"]
    private var mDict: [Int:String] = [0: "value1", 1: "value2", 2: "value3"]

    func getArrayIterator() -> IndexingIterator<[String]>
    {
        return mArray.makeIterator()
    }

    func getDictIterator() -> DictionaryIterator<Int, String>
    {
        return mDict.makeIterator()
    }
}

let container = Container()

for value in container.getArrayIterator()
{
    print("Value: \(value)")
}

for (key, value) in container.getDictIterator() // Type 'DictionaryIterator<Int, String>' (aka 'Dictionary<Int, String>.Iterator') does not conform to protocol 'Sequence'
{
    print("Key: \(key), value: \(value)")
}

Однако, глядя на документы для Dictionary.Iterator, кажется, что оно действительно соответствует в последовательность протокола.
РЕДАКТИРОВАТЬ : фактически говорится, что Dictionary.Iterator имеет отношение "Из протокола" Sequence

https://developer.apple.com/documentation/swift/dictionary/iterator

Почему этот код не работает?

1 Ответ

1 голос
/ 07 марта 2020

В общем, итератор - это не то, что вы можете сказать for...in; это причина, почему вы можете сказать for...in чему-то другому. Под капотом for...in на самом деле находится while l oop, который многократно вызывает next на итераторе. Теперь, когда вы посмотрели за кулисы, вы тоже должны это использовать.

Так, например, допустим, у нас есть словарь

let d = [1:"hey", 2:"ho"]

Тогда это:

for (i,s) in d {
    print(i, s)
}

эквивалентно этому:

var it = d.makeIterator()
while let (i,s) = it.next() {
    print(i,s)
}

И фактически под капотом первый является вторым. Существуют ситуации, когда заставить oop вести себя так, как вы хотите, может быть проще, если вы «развернете» for...in в форму итератора.

Теперь, в конкретном случае массива, который индексируется число, итератор является IndexingIterator, который сам имеет итератор - который сам имеет итератор и так далее. Это черепахи до самого конца, до тошноты:

let arr = [1,2,3]
let whoa = arr.makeIterator().makeIterator().makeIterator() // !!!!
for i in whoa {
    print(i)
}

Вы можете продолжать это определение whoa сколько угодно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...