【问题标题】:Lazy eager map evaluation懒人急图评测
【发布时间】:2014-10-29 14:12:33
【问题描述】:

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

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

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

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

  1. 地图的调用不会阻塞当前线程。
  2. 获取元素不会阻塞当前线程(以防之前有时间计算它并将结果存储在缓冲区中)。
  3. 可以处理无限列表,因为我们只预取少数结果(大约 8 个,取决于内核数量)。

所以这一切听起来都很好,您可能想知道问题出在哪里。问题是这个解决方案不是特别优雅的恕我直言。假设我共享的代码在 Java 和/或 Scala 中工作,要遍历由映射生成的可迭代元素中的元素,我只需要编写:

new CFMap(whateverFunction).apply(whateverIterable)

但是我想写的是这样的:

whateverIterable.bmap(whateverFunction)

在 Scala 中很常见(“b”代表缓冲),或者类似:

whateverThing.toBuffered.map(whateverFunction)

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

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

如果有不清楚的地方请告诉我。

【问题讨论】:

    标签: scala concurrency lazy-evaluation eager


    【解决方案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)
    }
    

    【讨论】:

    • 谢谢。这个问题不像例子那么具体。我将尝试以某种在 Scala 中可能有意义的方式来实现这一点(问题是缓冲区的可变性)。
    • 嗯,我明白了。我通过扩展 Iterable 的功能向您展示了如何使用您喜欢的语法。如果我完全错过了这个问题,我深表歉意。
    • 没关系,我想我可以把碎片拼起来。给我几天的时间来为此找个时间。再次感谢您。
    猜你喜欢
    • 2012-03-05
    • 1970-01-01
    • 1970-01-01
    • 2017-04-30
    • 2016-04-03
    • 2011-07-16
    • 1970-01-01
    • 2019-01-07
    相关资源
    最近更新 更多