【发布时间】:2014-10-29 14:12:33
【问题描述】:
在 Scala 中评估地图基本上有两种选择。
- 惰性求值计算需要下一个值时作为参数传递的函数。如果函数需要一小时才能执行,那么在需要该值时等待一小时。 (例如
Stream和Iterator) - 急切评估会在定义地图时计算函数。它会生成一个新列表(
Vector或其他)并存储结果,从而使程序在这段时间内处于忙碌状态。 - 使用
Future,我们可以在单独的线程中获取列表(Seq或其他),这意味着我们的线程不会阻塞,但必须存储结果。
所以我做了一些不同的事情,please check it here。
这是不久前的,所以我不记得我是否测试过。关键是要有一个映射同时(非阻塞)并且急切地应用于一组元素,填充缓冲区(计算机中核心数量的大小,不多 )。这意味着:
- 地图的调用不会阻塞当前线程。
- 获取元素不会阻塞当前线程(以防之前有时间计算它并将结果存储在缓冲区中)。
- 可以处理无限列表,因为我们只预取少数结果(大约 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