Продължавам да се стремя към функционален Swift и много се наслаждавам на предизвикателството. Работя с Transforms, които превръщат елементи в мързеливи последователности.
За да заявя грешката отпред, получавам: Не мога да конвертирам стойност от тип „Transform“ (известен още като „(Int) -> LazySequence>“) в очакван тип аргумент „() -> LazySequence‹[]>'
Проблемът ми е с композирането им, но трябва да дам някакъв контекст, за да покажа проблема.
Ето трансформацията:
typealias Transform<T, U> = (T) -> LazySequence<[U]>
И мога да дефинирам Forward Application:
precedencegroup LazyForwardApplication {
associativity: left
}
infix operator |~>: LazyForwardApplication
func |~> <T: LazySequenceProtocol, U>(
input: T,
transform: @escaping Transform<T.Elements.Element,U>
) -> LazySequence<FlattenSequence<LazyMapSequence<T.Elements, LazySequence<[U]>>>> {
return input.flatMap(transform)
}
Типът за връщане е малко залък, но работи добре:
let start = [10,20,30].lazy
let add4let add7000_8000: Transform<Int, Int> = {
let result = [ $0 + 7000, $0 + 8000]
print("> add7000_8000(\($0)) -> \(result)")
return result.lazy
}
let result2 = start |~> add7000_8000
result2.forEach{ print($0) }
// 7010, 8010, 7020, 8020, 7030, 8030
6: Transform<Int, Int> = {
let result = [ $0 + 4, $0 + 5, $0 + 6]
print("> add4let add7000_8000: Transform<Int, Int> = {
let result = [ $0 + 7000, $0 + 8000]
print("> add7000_8000(\($0)) -> \(result)")
return result.lazy
}
let result2 = start |~> add7000_8000
result2.forEach{ print($0) }
// 7010, 8010, 7020, 8020, 7030, 8030
6(\($0)) -> \(result)")
return result.lazy
}
// Обърнете внимание, че поставих отстраняването на грешки отчасти, за да мога да съм сигурен, че се случва лениво.
let result1 = start |~> add4let add7000_8000: Transform<Int, Int> = {
let result = [ $0 + 7000, $0 + 8000]
print("> add7000_8000(\($0)) -> \(result)")
return result.lazy
}
let result2 = start |~> add7000_8000
result2.forEach{ print($0) }
// 7010, 8010, 7020, 8020, 7030, 8030
6
result1.forEach{ print($0) }
// 14, 15, 16, 24, 25, 26, 34, 35, 36
И още един подобен пример:
let add7000_8000: Transform<Int, Int> = {
let result = [ $0 + 7000, $0 + 8000]
print("> add7000_8000(\($0)) -> \(result)")
return result.lazy
}
let result2 = start |~> add7000_8000
result2.forEach{ print($0) }
// 7010, 8010, 7020, 8020, 7030, 8030
И мога да свържа тези заедно в ред:
// Double application
let result3 = start |~> add4_5_6 |~> add7000_8000
result3.forEach{ print($0) }
// 7014, 8014, 7015, 8015, 7016, 8016,
// 7024, 8024, 7025, 8025, 7026, 8026,
// 7034, 8034, 7035, 8035, 7036, 8036
Но бих искал да мога и да ги композирам:
// Forward Composition
precedencegroup LazyForwardComposition {
associativity: right
}
infix operator >~>: LazyForwardComposition
func >~> <T, U: Sequence, V: Sequence>(
left: @escaping Transform<T,U>,
right: @escaping Transform<U,V>
) -> (T) -> LazySequence<FlattenSequence<LazyMapSequence<[U], LazySequence<[V]>>>> {
return { input in
let b: LazySequence<[U]> = left(input)
let c = b.flatMap(right)
return c
}
}
И ето къде получавам грешка:
let composed = add4_5_6 >~> add7000_8000
// ERROR IN ABOVE LINE: Cannot convert value of type
'Transform<Int, Int>' (aka '(Int) -> LazySequence<Array<Int>>')
to expected argument type
'(_) -> LazySequence<[_]>'
let result4 = start |~> composed
result4.forEach{ print($0) }
Резултатът ще излезе същият като резултат3
Заобиколих това няколко пъти, но продължавам да се забивам. Оценяват се всякакви мисли за това как да се разреши.
(Предишният ми въпрос е подобна територия, но различен проблем: Swift: Мързеливо капсулиране на вериги от карта, филтър, flatMap )
За детска площадка:
typealias Transform<T, U> = (T) -> LazySequence<[U]>
// And I can define Forward Application:
precedencegroup LazyForwardApplication {
associativity: left
}
infix operator |~>: LazyForwardApplication
func |~> <T: LazySequenceProtocol, U>(
input: T,
transform: @escaping Transform<T.Elements.Element,U>
) -> LazySequence<FlattenSequence<LazyMapSequence<T.Elements, LazySequence<[U]>>>> {
return input.flatMap(transform)
}
// The return type is a bit of a mouthful but it works fine:
let start = [10,20,30].lazy
let add4_5_6: Transform<Int, Int> = {
let result = [ $0 + 4, $0 + 5, $0 + 6]
print("> add4_5_6(\($0)) -> \(result)")
return result.lazy
}
// Note that I put the debug in partly so I can be sure that it's happening lazily.
let result1 = start |~> add4_5_6
result1.forEach{ print($0) }
// 14, 15, 16, 24, 25, 26, 34, 35, 36
// And another similar example:
let add7000_8000: Transform<Int, Int> = {
let result = [ $0 + 7000, $0 + 8000]
print("> add7000_8000(\($0)) -> \(result)")
return result.lazy
}
let result2 = start |~> add7000_8000
result2.forEach{ print($0) }
// 7010, 8010, 7020, 8020, 7030, 8030
// And I can chain these together inline:
// Double application
let result3 = start |~> add4_5_6 |~> add7000_8000
result3.forEach{ print($0) }
// 7014, 8014, 7015, 8015, 7016, 8016,
// 7024, 8024, 7025, 8025, 7026, 8026,
// 7034, 8034, 7035, 8035, 7036, 8036
// But I'd like to be able to compose them too:
// Forward Composition
precedencegroup LazyForwardComposition {
associativity: right
}
infix operator >~>: LazyForwardComposition
func >~> <T, U: Sequence, V: Sequence>(
left: @escaping Transform<T,U>,
right: @escaping Transform<U,V>
) -> (T) -> LazySequence<FlattenSequence<LazyMapSequence<[U], LazySequence<[V]>>>> {
return { input in
let b: LazySequence<[U]> = left(input)
let c = b.flatMap(right)
return c
}
}
// And here's where I get an error:
let composed = add4_5_6 >~> add7000_8000
// ERROR IN ABOVE LINE: Cannot convert value of type 'Transform<Int, Int>' (aka '(Int) -> LazySequence<Array<Int>>') to expected argument type '(_) -> LazySequence<[_]>'
let result4 = start |~> composed
result4.forEach{ print($0) }
// The result would come out the same as result3