SE情報技術研究会’s blog

http://se-info-tech.connpass.com

2016-01-09 第11回 関数型プログラミング勉強会(Scala)の振り返り part.1

第5章 正格と遅延

前回の続きより

Exercise 5.12

GitHubにあがってる解答で問題なし。

まず、fibsViaUnfoldの実装を見てみる。

val fibsViaUnfold = 
  unfold((0,1)) { case (f0,f1) => Some((f0,(f1,f0+f1))) }

これはコメントにあるようにp => p matchを省略してある。

Scala provides shorter syntax when the first action of a function literal is to match on an expression.

Scalaは関数リテラルの最初の処理が式にマッチする場合 より短いシンタックスを供給する

The function passed to unfold in fibsViaUnfold is equivalent to p => p match { case (f0,f1) => ... }, but we avoid having to choose a name for p, only to pattern match on it.

fibsViaUnfoldunfoldに渡した関数は p => p match { case (f0,f1) => ... }と同値であるが パターンマッチでしか使われないpをわざわざ命名することをここでは避けた

あと、fromViaUnfoldを段階的に見てみた。

fromViaUnfold(2)
 ↓
unfold(2)(n => Some((n,n+1)))
 ↓
cons(2, unfold(2+1)(n => Some((n,n+1)))
 ↓
cons(2, cons(3, unfold(3+1)(n => Some((n,n+1)))
 ↓
cons(2, cons(3, cons(4, unfold(4+1)(n => Some((n,n+1)))
 ↓
…
 ↓
Stream(2, 3, 4...略)

また、onesViaUnfoldは下記にもできる

val onesViaUnfold = constantViaUnfold(1)

Exercise 5.13

GitHubにあがってる解答で問題なし。

Exercise 5.14

GitHubにあがってる解答で問題なし。

Exercise 5.15

GitHubにあがってる解答で問題なし。

Exercise 5.16

解答に値を入れて段階的に見ていく。

Stream(1,2,3).scanRight(0)(_ + _)
 ↓
Stream(1,2,3).foldRight((z, Stream(z)))((a, p0) => {
      lazy val p1 = p0
      val b2 = f(a, p1._1)
      (b2, cons(b2, p1._2))
    })._2
 ↓
Stream(2,3).foldRight((0, Stream(0)))((1, (0, Stream(0))) => {
      lazy val p1 = (0, Stream(0))
      val b2 = 1 + 0
      (1, cons(1, Stream(0))
    })._2
 ↓
Stream(3).foldRight(1, Stream(1,0))((2, (1,Stream(1,0)))) => {
      lazy val p1 = (1, Stream(1,0))
      val b2 = 2 + 1
      (3, cons(3, Stream(1,0))
    })._2
 ↓
Stream().foldRight(3, Stream(3,1,0))((3, (3,Stream(3,1,0)))) => {
      lazy val p1 = (3, Stream(3,1,0))
      val b2 = 3 + 3
      (6, cons(6, Stream(3,1,0))
    })._2
 ↓
Stream(6,3,1,0)

その他

ScalaのStreamは次のパターンで表現できる(両方とも同じである)

  • Stream(1,2,3,4)
  • Cons(1, Cons(2, Cons(3, Cons(4, empty))))