Scalaを趣味で触るついでに関数型プログラミングに慣れる(予定)-1

scalaを勉強してみることにした。

 

調べてみるとこれが良いって色んな人が書いているので、流される性格の人としては 読んでみるしかない。

 

第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

 

三日坊主にならないようにしよう