2015年5月26日火曜日

scala関数型デザイン&プログラミング P93

Exercise 5.11 より汎用的なunfoldを記述せよ

解答をみるとf(z) matchとしている。柔軟な発想が必要なようだ。
def unfold[A, S](z: S)(f: S => Option[(A, S)]): Stream[A] =
  f(z) match {
    case Some((h,s)) => cons(h, unfold(s)(f))
    case None => empty
  }
これまで、でてきた生成関数に共通する部分をみると
 def 自分自身(引数1)=cons(h,自分自身(引数2))
となっているので、引数1から引数2への変換のためにfという関数を用意し、同時にそのfの関数でhも求めるようにしている。

Exercise 5.12 fibs、from、constant,onesをunfoldを使って実装する。
   def fibs4(n1:Int,n2:Int)=
   unfold((n1,n2))( ((nn1,nn2)) => Some( (nn1,(nn2,nn1+nn2) ) )  )
としたが、なぜかエラー 1引数の関数にせよ。そのためにcaseパターンを使うということか?
解答のとおり
def fibs3(n1:Int,n2:Int)=
   unfold((n1,n2))( p=>p match  {case  (nn1,nn2) => Some( (nn1,(nn2,nn1+nn2) ) )  }  )
とするとうまくいく。 1引数としてpをとり、その戻り値がp match  {case  (nn1,nn2) => Some( (nn1,(nn2,nn1+nn2) ) )  } ということになるんだろうか。回りくどい感じがすると思うのは私だけだろうか。
省略形が
def fibs3(n1:Int,n2:Int)=
   unfold((n1,n2)) {case  (nn1,nn2) => Some( (nn1,(nn2,nn1+nn2) ) )  }
だとか。
 これ以降はmatchは使わなくてもよいようだ。
   def from2(n:Int):Stream[Int]=     unfold(n)( n=>Some((n,n+1)) )
def constant2[A](a:A):Stream[A]= unfold(a)(a=>Some(  (a , a )   ) )
def ones:Stream[Int]=unfold(1)(i=>Some((i,i)))



0 件のコメント:

コメントを投稿