Scalaを趣味で触るついでに関数型プログラミングに慣れる(予定)-1
scalaを勉強してみることにした。
調べてみるとこれが良いって色んな人が書いているので、流される性格の人としては 読んでみるしかない。
Scala関数型デザイン&プログラミング―Scalazコントリビューターによる関数型徹底ガイド
- 作者: Paul Chiusano,Rúnar Bjarnason,株式会社クイープ
- 出版社/メーカー: インプレス
- 発売日: 2015/04/30
- メディア: Kindle版
- この商品を含むブログ (3件) を見る
第2章
/**
* シングルトンオブジェクト
*/
object MyModule {
/*
整数を受け取り整数を返す純粋関数
*/
def abs(n: Int): Int =
if (n < 0) -n
else n
/*
プライベートメソッドMyModule内からしか呼び出せない
*/
private def formatAbs(x: Int) = {
val msg = "The absolute value of %d is %d"
msg.format(x, abs(x))
}
/*
Unitはjavaのvoidに相当する
*/
def main(args: Array[String]): Unit = {
println(formatAbs(-42))
}
}
javaと大分違うな
object MyModule
これでシングルトンオブジェクトの宣言となる。とな。
あとは、型アノテーションがこんな感じ。
(n: Int)
変数宣言はこう。
val num1: Int = 0
val num2 = 0
num2 = 1 //この行はコンパイルエラー
var num3: Int = 0
var num4 = 0
num4 = 1
valでもvarでも宣言可能だが、valで宣言するとImmutableになる。
変なところで書き換えられないためにも、valを使うほうが安全で安心だなぁ。
2.4章
高階関数:関数に関数を渡す
factorialのサンプル実装を書いてみる。
goという関数をローカル定義
Scalaのヘルパー関数ではgoまたはloopという名前を使用するのが慣例らしい。
で、StackOverFlowしないように末尾再帰を使ってねと。
@annotation.tailrec というアノテーションで末尾再帰かどうかをチェックしてくれる。
def factorial(n: Int): Int = {
@annotation.tailrec
def go(n: Int, acc: Int): Int = {
if (n <= 0)
acc
else go(n - 1, n * acc)
}
go(n, 1)
}
Excersizeとしてn番目のフィボナッチを求めるのを書けとの事
Signatureはこれ。
def fib(n: Int): Int = ???
scalaは未実装部分を???にしておいて他の実装を進められる。
これ、すごい便利だと思う。実装忘れがなくなるし、並行作業しやすい。
まずは単純に再帰で書いてみる・
とりあえずササっと書い、、けないので、文法を調べる。
scalaでのcase文はmatchってのを使うらしい。
def fib(n: Int): Int = {
n match {
case 0 => 0
case 1 => 1
case 2 => 1
case _ => fib(n - 2) + fib(n - 1)
}
}
case _
で0,1,2以外の残りを処理する。
caseについてはこんな書き方ができるらしい。今回のロジックだとこっちの方が綺麗だと感じた。
ただ、末尾再帰ではないのでもう少し。
def fib(n: Int): Int = n match {
case 0 => 0
case 1 => 1
case 2 => 1
case _ => fib(n - 2) + fib(n - 1)
}
factorialと同じ手法で末尾再帰してみる。
def fib(n: Int): Int = {
@annotation.tailrec
def go(n: Int, pre: Int, cur: Int): Int = {
if (n == 0) pre
else go(n - 1, cur, pre + cur)
}
go(n, 0, 1)
}
答え見てみたけど、一緒。
fpinscala/GettingStarted.scala at master · fpinscala/fpinscala · GitHub
三日坊主にならないようにしよう