是否可以使用 'yield' 來生成 'Iterator' 而不是 Scala 中的列表? (Is it possible to use 'yield' to generate 'Iterator' instead of a list in Scala?)


問題描述

是否可以使用 'yield' 來生成 'Iterator' 而不是 Scala 中的列表? (Is it possible to use 'yield' to generate 'Iterator' instead of a list in Scala?)

Is it possible to use yield as an iterator without evaluation of every value?

It is a common task when it is easy to implement complex list generation, and then you need to convert it into Iterator, because you don't need some results...


參考解法

方法 1:

Sure. Actually, there are three options for non-strictness, which I list below. For the examples, assume:

val list = List.range(1, 10)
def compute(n: Int) = {
    println("Computing "+n)
    n * 2
}
  1. Stream. A Stream is a lazily evaluated list. It will compute values on demand, but it will not recompute values once they have been computed. It is most useful if you'll reuse parts of the stream many times. For example, running the code below will print "Computing 1", "Computing 2" and "Computing 3", one time each.

    val stream = for (n <- list.toStream) yield compute(n)
    val third = stream(2)
    println("%d %d" format (third, stream(2)))
    
  2. view. A view is a composition of operations over a base collection. When examining a view, each element examined is computed on-demand. It is most useful if you'll randomly access the view, but will never look but at a small part of it. For example, running the code below will print "Computing 3" two times, and nothing else (well, besides the result).

    val view = for (n <- list.view) yield compute(n)
    val third = view(2)
    println("%d %d" format (third, view(2)))
    
  3. Iterator. An Iterator is something that is used to lazily walk through a collection. One can think of it as a "one-shot" collection, so to speak. It will neither recompute nor store any elements -- once an element has been "computed", it cannot be used again. It is a bit more tricky to use because of that, but it is the most efficient one given these constraints. For example, the following example needs to be different, because Iterator does not support indexed access (and view would perform badly if written this way), and the code below prints "Computing 1", "Computing 2", "Computing 3", "Computing 4", "Computing 5" and "Computing 6". Also, it prints two different numbers at the end.

    val iterator = for (n <- list.iterator) yield compute(n)
    val third = iterator.drop(2).next
    println("%d %d" format (third, iterator.drop(2).next))
    

方法 2:

Use views if you want lazy evaluation, see Views.

The Scala 2.8 Collections API is a fantastic read if you're going to use the Scala collections a lot.

方法 3:

I have a List...

scala>  List(1, 2, 3)
res0: List[Int] = List(1, 2, 3)

And a function...

scala> def foo(i : Int) : String = { println("Eval: " + i); i.toString + "Foo" }
foo: (i: Int)String

And now I'll use a for-comprehension with an Iterator...

scala> for { i <- res0.iterator } yield foo(i)
res2: Iterator[java.lang.String] = non-empty iterator

You can use a for comprehension on any type with flatMapmap and filter methods. You could also use the views:

scala> for { i <- res0.view } yield foo(i)
res3: scala.collection.SeqView[String,Seq[_]] = SeqViewM(...)

Evaluation is non-strict in either case...

scala> res3.head
Eval: 1
res4: String = 1Foo

(by yuraDaniel C. Sobralllemiengoxbow_lakes)

參考文件

  1. Is it possible to use 'yield' to generate 'Iterator' instead of a list in Scala? (CC BY-SA 3.0/4.0)

#yield-return #continue #yield-keyword #yield #scala






相關問題

Bagaimana saya bisa membuat `menunggu ...` bekerja dengan `yield return` (yaitu di dalam metode iterator)? (How can I make `await …` work with `yield return` (i.e. inside an iterator method)?)

收益回報使用 (yield return usage)

無法將“<>d__6”類型的對象轉換為“System.Object[]”類型 (Unable to cast object of type '<>d__6' to type 'System.Object[]')

使用 yield return 時 GetEnumerator() 方法會發生什麼? (What happens to GetEnumerator() method when yield return is used?)

抓取回調函數 (Scrapy callback function)

我可以在 VB.NET 中為 IEnumerable 函數實現收益返回嗎? (Can I implement yield return for IEnumerable functions in VB.NET?)

使用具有代碼訪問安全性的 C# 迭代器方法時出現問題 (Problem using C# iterator methods with code access security)

如何使用收益返回和遞歸獲得每個字母組合? (How do I get every combination of letters using yield return and recursion?)

是否可以使用 'yield' 來生成 'Iterator' 而不是 Scala 中的列表? (Is it possible to use 'yield' to generate 'Iterator' instead of a list in Scala?)

yield return 除了 IEnumerable 之外還有其他用途嗎? (Does yield return have any uses other than for IEnumerable?)

這個函數可以用更有效的方式編寫嗎? (Can this function be written in more efficient way?)

當我在代碼中引入產量時,它在 python 中不起作用 (when i introduced yield in code it doesn't work in python)







留言討論