乱数を生成するfor..yield
30分プログラム、その418。mapやらfilterを定義すれば、俺々データ構造でもforが使えるらしいので、試してみる。
というわけで、for(n <- stream) ..とするだけで乱数を生成できるストリームを作ってみた。
ちなみにscala.Randomはdeprecatedで、scala.util.Randomを使うべきらしいけど、ボクのScala処理系は古いらしくてscala.util.Randomは無かったのでdeprecatedを使ってる。
使い方
// 長さ5のストリーム scala> val r = new RandomStream(5,new Random) r: RandomStream = RandomStream@f7545d // printしてみる scala> for(n <- r) println(n) 190666319 -1796022525 666838077 671772833 1415902003 // printするたびに値が違う scala> for(n <- r) println(n) 1132383051 -494624490 1443618707 1804687541 -78546838 // yieldもできる scala> for(n <- r) yield n res63: List[Int] = List(-795386642, -1038537116, -1497499699, 1275316298, -1514816727) // 正の乱数だけを取り出す scala> for(n <- r if n > 0) yield n res64: List[Int] = List(357014503)
ソースコード
class RandomStream(n : Int,random : Random) { private def next = new RandomStream(n-1,random) def map[A](f : Int => A) : List[A] = if(n == 0) List() else f(random nextInt)::(next map f) def filter(f : Int => Boolean) : List[Int] = { if(n == 0) List() else { val r = random.nextInt() if(f(r)) r::(next filter f) else next filter f } } def foreach(f : Int => Unit) : Unit = if(n == 0) () else{ f(random nextInt) next foreach(f) } }