Вау снова! Это круто. Спасибо, что нашли время, чтобы написать это. Хотя это не так много строк кода, он представляет собой довольно значительный набор методов. Моя следующая задача - обдумать, как добавить в конвейер ленивый декартовой продукт ...
я есть список животных:
let animals = ["bear", "dog", "cat"]
И несколько способов преобразовать этот список:
typealias Transform = (String) -> [String]
let containsA: Transform = { $0.contains("a") ? [$0] : [] }
let plural: Transform = { [$0 + "s"] }
let double: Transform = { [$0, $0] }
Немного в стороне, они аналогичны фильтру (выходы 0 или 1 элемент), карте (ровно 1 элемент) и плоской карте (более 1 элемента) соответственно, но определены единообразным образом, чтобы их можно было обрабатывать согласованно.
Я хочу создать ленивый итератор, который применяет массив этих преобразований к списку животных:
extension Array where Element == String {
func transform(_ transforms: [Transform]) -> AnySequence<String> {
return AnySequence<String> { () -> AnyIterator<String> in
var iterator = self
.lazy
.flatMap(transforms[0])
.flatMap(transforms[1])
.flatMap(transforms[2])
.makeIterator()
return AnyIterator {
return iterator.next()
}
}
}
}
а это значит, я могу лениво делать:
let transformed = animals.transform([containsA, plural, double])
и проверить результат:
print(Array(transformed))
Я доволен, насколько это кратко, но ясно:
.flatMap(transforms[0])
.flatMap(transforms[1])
.flatMap(transforms[2])
является проблемой, поскольку это означает, что функция преобразования будет работать только с массивом из 3 преобразований.
Редактировать: Я пытался:
var lazyCollection = self.lazy
for transform in transforms {
lazyCollection = lazyCollection.flatMap(transform) //Error
}
var iterator = lazyCollection.makeIterator()
но в отмеченной строке я получаю ошибку:
Невозможно присвоить значение типа 'LazyCollection <FlattenCollection <LazyMapCollection <Array <String>, [String] >>>' для типа 'LazyCollection <Array <String >>'
что я понимаю, потому что каждый раз вокруг цикла добавляется еще одна плоская карта, поэтому тип меняется.
Как я могу заставить функцию преобразования работать с массивом любого количества преобразований?
Одно WET решение для ограниченного числа преобразований будет (но YUK!)
switch transforms.count {
case 1:
var iterator = self
.lazy
.flatMap(transforms[0])
.makeIterator()
return AnyIterator {
return iterator.next()
}
case 2:
var iterator = self
.lazy
.flatMap(transforms[0])
.flatMap(transforms[1])
.makeIterator()
return AnyIterator {
return iterator.next()
}
case 3:
var iterator = self
.lazy
.flatMap(transforms[0])
.flatMap(transforms[1])
.flatMap(transforms[2])
.makeIterator()
return AnyIterator {
return iterator.next()
}
default:
fatalError(" Too many transforms!")
}
Весь код:
let animals = ["bear", "dog", "cat"]
typealias Transform = (String) -> [String]
let containsA: Transform = { $0.contains("a") ? [$0] : [] }
let plural: Transform = { [$0 + "s"] }
let double: Transform = { [$0, $0] }
extension Array where Element == String {
func transform(_ transforms: [Transform]) -> AnySequence<String> {
return AnySequence<String> { () -> AnyIterator<String> in
var iterator = self
.lazy
.flatMap(transforms[0])
.flatMap(transforms[1])
.flatMap(transforms[2])
.makeIterator()
return AnyIterator {
return iterator.next()
}
}
}
}
let transformed = animals.transform([containsA, plural, double])
print(Array(transformed))