这是我上一个问题的后续行动。假设我想要Stream
匹配^a+b+$
的所有字符串(一个或多个" a"然后一个或多个" b")。
我的编码如下:
def interleave(s1:Stream[String], s2:Stream[String]): Stream[String] = if (s1.isEmpty) s2 else Stream.cons(s1.head, interleave(s2, s1.tail)) def generate(s1:Stream[String], s2:Stream[String]): Stream[String] = if (s1.isEmpty) s1 else interleave(s2.map(s1.head + _), generate(s1.tail, s2)) def as:Stream[String] = Stream.cons("a", as.map(_ + "a")) def bs:Stream[String] = Stream.cons("b", bs.map(_ + "b")) def solve = generate(as, bs)
不幸的是solve
因out of memory
而失败。但是它适用于有限流:例如solve(as take 10, bs take 10)
您如何修复上述代码?您是否希望采用其他方式来解决问题?
答案 0 :(得分:2)
这个怎么样:
scala> val asbs = for(n <- Stream.from(2);k <- 1 until n) yield "a"*k + "b"*(n-k)
asbs: scala.collection.immutable.Stream[String] = Stream(ab, ?)
scala> asbs.take(10).toList
res0: List[String] = List(ab, abb, aab, abbb, aabb, aaab, abbbb, aabbb, aaabb, aaaab)
scala>
答案 1 :(得分:2)
问题在于,为了能够调用interleave
,必须计算generate
:
def generate(s1:Stream[String], s2:Stream[String]): Stream[String] =
if (s1.isEmpty) ... else interleave(..., generate(s1.tail, s2))
因此,生成将递归调用自身直到s1.isEmpty
,此时它将最终调用所有挂起的interleave
。由于s1
是无限的,因此永远不会为空。
如果将interleave
的第二个参数转换为by-name参数,则递归可以延迟:
def interleave(s1:Stream[String], s2: => Stream[String]): Stream[String] =