我正在查看Rng来源,了解它们如何生成随机值列表。
他们定义了一个函数fill
:
def fill(n: Int): Rng[List[A]] = sequence(List.fill(n)(this))
其中sequence
只是从Traverse.sequence
调用scalaz
:
def sequence[T[_], A](x: T[Rng[A]])(implicit T: Traverse[T]): Rng[T[A]] =
T.sequence(x)
换句话说,他们会创建一个临时列表List[Rang[A]]
,然后应用sequence: List[Rng[A]] => Rng[List[A]]
。我看它是如何工作的,但临时列表看起来对我来说是浪费内存。这绝对必要吗?可以改进吗?
答案 0 :(得分:1)
这是一个稍微快一点的实现。我没有剖析,看看堆上是否有明显的影响。我做了一个粗略的计时测试,花了大约70%的时间Rng.fill
用随机的Int填充1M项目列表。我没有试图找出这些与不同大小的列表如何缩放。见https://gist.github.com/drstevens/77db6bab6b1e995dac13
def fill[A](a: Rng[A], count: Int): Rng[List[A]] =
Stream.from(0).take(count).traverseU(_ => a).map(_.toList)
有趣的是,在unsafePerformIO
之前不会评估toList。