用trait做random value generator
這是常見的一種架構,先定義一個trait:trait Generator[T] { def generate : T}
然後藉由實做這個trait得出各種不同type的random value generators:
val integers = new Generator[Int] { override def generate: Int = new Random().nextInt() } val booleans = new Generator[Boolean] { override def generate: Boolean = integers.generate > 0} val pairs = new Generator[(Int,Int)] { override def generate: (Int, Int) = (integers.generate, integers.generate) }
這樣定義ok, 但是使用上很麻煩,每次延伸一個新的種類,都要new一個generator出來,能不能不要用這種方式呢?
嘗試用for試試看
我們希望達到的類似這樣的架構來定義新的種類的generators (所以for statment中的generators不限於collection type, 而是某個有implement map的object都可):根據我們之前在解讀for的筆記中知道,compiler會把以上的for statement解譯成以下:
所以我們只要幫我們的random generator 實作map, flatmap就可以用for來使用。
我們的Generator trait新增了兩個 methods:
trait Generator[T] { self => //相當於 Generator.this
def generate : T //產生random value //回傳一個Generator[S],
//其generate的定義為把self產生的random value經過f mapping def map[S](f:T => S):Generator[S] = new Generator[S] { override def generate: S = f(self.generate) } //回傳一個Generator[S],
//其generate的定義為把self產生的random value經過f map到 Generator[S]的instance
//然後回傳此generator的generate method
def flatMap[S](f: T => Generator[S]): Generator[S] = new Generator[S] {
def generate : S = f(self.generate).generate } }
如何解讀新的Generator?
如果用這個Generator trait的定義來實作booleans的隨機產生器的話,可以看到以下的substitution steps:所以booleans被替換成跟我們在上一段的寫法一樣。
why all the efforts?!
解讀用for定義pairs的generator:
好難懂!!!!! 以後有遇到需求再回來研究吧!
沒有留言:
張貼留言