懒惰的热切地图评估

时间:2014-10-29 14:12:34

标签: scala concurrency lazy-evaluation eager

在Scala中基本上有两种选择来评估地图。

  • 延迟评估计算机在需要下一个值时作为参数传递的函数。如果该功能需要一个小时才能执行,那么在需要该值时需要等待一个小时。 (例如StreamIterator
  • 急切评估计算定义地图时的功能。它生成一个新列表(Vector或其他)并存储结果,使程序在那段时间内处于忙碌状态。
  • 使用Future我们可以在单独的线程中获取列表(Seq或其他),这意味着我们的线程不会阻塞,但必须存储结果。

所以我做了一些不同的事情,please check it here

这是不久前的,所以我不记得我是否测试过它。关键是要有一个同时应用(非阻塞)和急切应用于一组元素的地图,填充缓冲区(计算机中核心数量的大小,以及不再 )。这意味着:

  1. 调用地图不会阻止当前线程。
  2. 获取元素不会阻止当前线程(如果有时间计算它并将结果存储在缓冲区中)。
  3. 无限列表可以处理,因为我们只预取一些结果(大约8,取决于核心数量)。
  4. 所以这听起来非常好,你可能想知道问题是什么。问题是这个解决方案并不是特别优雅恕我直言。假设我共享的代码在Java和Scala中工作,迭代地图生成的迭代中的元素我只需要写:

    new CFMap(whateverFunction).apply(whateverIterable)
    

    但是我想写的是:

    whateverIterable.bmap(whateverFunction)
    

    正如Scala中常见的那样(' b'用于缓冲),或者类似于:

    whateverThing.toBuffered.map(whateverFunction)
    

    他们中的任何一个都适合我。所以问题是,我怎样才能在Scala中以惯用的方式做到这一点?一些选择:

    • Monads :创建一个新的集合" Buffered"所以我可以使用toBuffered方法(应该作为隐式添加到以前的方法)并实现map以及此缓冲事物的所有其他内容(听起来非常有用)。
    • 隐含:创建一个隐式方法来转换通常的集合或它们的超类(我不确定它应该是哪一个,Iterable可能?)到我可以应用.bmap方法并从中获取内容的其他内容,可能是可迭代的。
    • 其他:到目前为止我可能还没有考虑过很多选项。有些图书馆可能已经实现了这一点(我实际上对相反的情况感到惊讶,我可以'相信没有人想过这个。)使用已经完成的东西通常是一个好主意。

    如果不清楚,请告诉我。

1 个答案:

答案 0 :(得分:1)

您正在寻找的是“pimp-my-library”模式。看看:

object CFMapExtensions {
  import sanity.commons.functional.CFMap
  import scala.collection.JavaConversions._

  implicit class IterableExtensions[I](i: Iterable[I]) {
    def bmap[O](f: Function1[I, O]): Iterable[O] = new CFMap(f).apply(asJavaIterable(i))
  }

  implicit class JavaIterableExtensions[I](i: java.lang.Iterable[I]) {
    def bmap[O](f: Function1[I, O]): Iterable[O] = new CFMap(f).apply(i)
  }

  // Add an implicit conversion to a java function.
  import java.util.function.{Function => JFunction}
  implicit def toJFunction[I, O](f: Function1[I, O]): JFunction[I, O] = {
    new JFunction[I, O]() {
      def apply(t: I): O = f(t)
    }
  }
}

object Test extends App {
  import CFMapExtensions._
  List(1,2,3,4).bmap(_ + 5).foreach(println)
}