scala中的种子在nicta的rng lib中

时间:2015-11-20 22:02:42

标签: scala random

我正在使用NICTA的RNG库,我希望我的RNG在测试中具有确定性。所以,假设我只想让下面的代码始终正确。

Rng.chooseint(0, 5).run.unsafePerformIO == 3 

但我找不到任何设置种子的方法,run方法不接受任何参数。有人可以帮忙吗?

1 个答案:

答案 0 :(得分:1)

嗯,this issue已经开放了将近一年,所以我认为你在现成的支持方面只是运气不好。

RngOp不提供公共构造函数或折叠的事实使得定义自己不方便,但并非不可能:

import com.nicta.rng._
import java.util.Random
import scala.annotation.tailrec

class NextBitsRandom(seed: Long) extends Random(seed) {
  def nextBits(bits: Int): Int = super.next(bits)
}

def runWithSeed[A](rng: Rng[A], seed: Long): A = {
  @tailrec def loop(g: Rng[A], r: NextBitsRandom): A = g.resume match {
    case RngTerm(a) => a
    case RngCont(op) =>
      val nop = op.store.map(s => RngOp.store(s.imap(r.nextBits))).getOrElse(op)
      nop.seed.foreach(r.setSeed)
      loop(nop.extract, r)
  }

  loop(rng, new NextBitsRandom(seed))
}

fold方法可以让我们跳过storegetOrElse上那种笨重的地图,但这很好用:

scala> runWithSeed(Rng.chooseint(0, 5), 0L)
res0: Int = 4

scala> runWithSeed(Rng.chooseint(0, 5), 0L)
res1: Int = 4

scala> runWithSeed(Rng.chooseint(0, 5), 1L)
res2: Int = 3

scala> runWithSeed(Rng.alphanumerics(10), 101L)
res3: List[Char] = List(M, h, Z, H, t, M, Z, H, c)

scala> runWithSeed(Rng.alphanumerics(10), 1001L)
res4: List[Char] = List(N, X, K, O, 6, C, L)

你可以尝试提交类似这样的东西作为#20的修复 - 如果它在库中,实现会更清晰,因为你可以使用RngOp构造函数。这是一个非常合理的想法(如果我没记错的话,以前版本的API确实支持它。)