如何封装 Lazy Swift 函数的组合?
How can I encapsulate composition of Lazy Swift Functions?
我需要一系列函数来处理字符串数组以生成其他字符串数组...
假设我开始于:
let animals = ["ant", "bear", "cat"]
有些函数会增加数组中的元素。例如:
extension String {
func double() -> [String] {
print("double")
return [self, self]
}
}
print( animals.flatMap { [=12=].double() } )
//double
//double
//double
["ant", "ant", "bear", "bear", "cat", "cat"]
有的会减少元素的数量。例如:
extension String {
func endsIn(_ endString: String) -> Bool {
print("endsIn")
return hasSuffix(endString)
}
}
print( animals.filter { [=13=].endsIn("t") } )
//endsIn
//endsIn
//endsIn
//["ant", "cat"]
我想组合这些函数,因为可能性的范围很大,所以我想尽量保持惰性:
let lazyComposition = animals
.lazy
.flatMap { [=14=].double() }
.filter { [=14=].endsIn("t") }
for x in lazyComposition {
print(">>>>>>>>>>> \(x)")
}
//double
//endsIn
// >>>>>>>>>>> ant
//endsIn
// >>>>>>>>>>> ant
//double
//endsIn
//endsIn
//double
//endsIn
// >>>>>>>>>>> cat
//endsIn
// >>>>>>>>>>> cat
我想封装这个函数组合。
我想我快到了:
extension Array where Element == String {
func combined() -> AnySequence<[String]> {
return AnySequence<[String]> { () -> AnyIterator<[String]> in
var iterator = self
.lazy
.flatMap { [=15=].double() }
.filter { [=15=].endsIn("t") }
return AnyIterator {
return iterator.next() // #ERROR#
}
}
}
}
for x in animals.combined() {
print(">>>>>>>>>>> \(x)")
}
但我在标记为#ERROR# 的行上收到错误消息:'LazyFilterCollection < FlattenCollection < LazyMapCollection < Array < String > , [String] > > > ' 类型的值没有成员'next'
任何解决这个问题的帮助表示赞赏。
或者建议其他方法来实现这一目标。
谢谢
阿达胡斯
首先,Sequence
或Collection
不能用作Iterator
,所以你的这部分代码很混乱:
var iterator = self
.lazy
.flatMap { [=10=].double() }
.filter { [=10=].endsIn("t") }
局部变量 iterator
是 Collection
(具体来说是 LazyFilterCollection <...>
,如您在错误消息中看到的那样),而不是 Iterator
.
其次,AnySequence
或 AnyIterator
将元素类型作为其通用参数。
以上两点固定后,你可以这样写:
extension Array where Element == String {
func combined() -> AnySequence<String> {
return AnySequence<String> { () -> AnyIterator<String> in // <- specify Element type as `String`
var iterator = self
.lazy
.flatMap { [=11=].double() }
.filter { [=11=].endsIn("t") }
.makeIterator() // <- make `Iterator` from `Collection`
return AnyIterator {
return iterator.next()
}
}
}
}
let animals = ["ant", "bear", "cat"]
for x in animals.combined() {
print(">>>>>>>>>>> \(x)")
}
输出:
double
endsIn
>>>>>>>>>>> ant
endsIn
>>>>>>>>>>> ant
double
endsIn
endsIn
double
endsIn
>>>>>>>>>>> cat
endsIn
>>>>>>>>>>> cat
我需要一系列函数来处理字符串数组以生成其他字符串数组...
假设我开始于:
let animals = ["ant", "bear", "cat"]
有些函数会增加数组中的元素。例如:
extension String {
func double() -> [String] {
print("double")
return [self, self]
}
}
print( animals.flatMap { [=12=].double() } )
//double
//double
//double
["ant", "ant", "bear", "bear", "cat", "cat"]
有的会减少元素的数量。例如:
extension String {
func endsIn(_ endString: String) -> Bool {
print("endsIn")
return hasSuffix(endString)
}
}
print( animals.filter { [=13=].endsIn("t") } )
//endsIn
//endsIn
//endsIn
//["ant", "cat"]
我想组合这些函数,因为可能性的范围很大,所以我想尽量保持惰性:
let lazyComposition = animals
.lazy
.flatMap { [=14=].double() }
.filter { [=14=].endsIn("t") }
for x in lazyComposition {
print(">>>>>>>>>>> \(x)")
}
//double
//endsIn
// >>>>>>>>>>> ant
//endsIn
// >>>>>>>>>>> ant
//double
//endsIn
//endsIn
//double
//endsIn
// >>>>>>>>>>> cat
//endsIn
// >>>>>>>>>>> cat
我想封装这个函数组合。 我想我快到了:
extension Array where Element == String {
func combined() -> AnySequence<[String]> {
return AnySequence<[String]> { () -> AnyIterator<[String]> in
var iterator = self
.lazy
.flatMap { [=15=].double() }
.filter { [=15=].endsIn("t") }
return AnyIterator {
return iterator.next() // #ERROR#
}
}
}
}
for x in animals.combined() {
print(">>>>>>>>>>> \(x)")
}
但我在标记为#ERROR# 的行上收到错误消息:'LazyFilterCollection < FlattenCollection < LazyMapCollection < Array < String > , [String] > > > ' 类型的值没有成员'next'
任何解决这个问题的帮助表示赞赏。 或者建议其他方法来实现这一目标。 谢谢 阿达胡斯
首先,Sequence
或Collection
不能用作Iterator
,所以你的这部分代码很混乱:
var iterator = self
.lazy
.flatMap { [=10=].double() }
.filter { [=10=].endsIn("t") }
局部变量 iterator
是 Collection
(具体来说是 LazyFilterCollection <...>
,如您在错误消息中看到的那样),而不是 Iterator
.
其次,AnySequence
或 AnyIterator
将元素类型作为其通用参数。
以上两点固定后,你可以这样写:
extension Array where Element == String {
func combined() -> AnySequence<String> {
return AnySequence<String> { () -> AnyIterator<String> in // <- specify Element type as `String`
var iterator = self
.lazy
.flatMap { [=11=].double() }
.filter { [=11=].endsIn("t") }
.makeIterator() // <- make `Iterator` from `Collection`
return AnyIterator {
return iterator.next()
}
}
}
}
let animals = ["ant", "bear", "cat"]
for x in animals.combined() {
print(">>>>>>>>>>> \(x)")
}
输出:
double
endsIn
>>>>>>>>>>> ant
endsIn
>>>>>>>>>>> ant
double
endsIn
endsIn
double
endsIn
>>>>>>>>>>> cat
endsIn
>>>>>>>>>>> cat