第2章：What is 関数型言語?

Scalaの醍醐味は関数型言語とオブジェクト指向言語のハイブリッドだ！

今回はオブジェクト指向をやっている人には馴染みが薄い、
関数型言語について語るよ。

# 関数型言語って何？
関数を駆使してプログラミングできる言語が、__関数型言語だ!__。
関数とはオブジェクト指向でいうと__「メソッド」__みたいなもんだ。
意味は違うけどね。数学的な例だと、

    y = sin(x)

これは引数`x`を与えると、`sin`が計算して値をyに代入するんだ。
ここでは`sin(x)`が関数だよ。

次にScalaで関数を作ってみるよ。

```FunctionExample.scala
object FunctionExample{
  def main(args: Array[String]){

    var calculate = (x: Int) => x + 5 : Int

    printf("y=%s \n", calculate(1))
    printf("y=%s \n", calculate(2))
  }
}
```
実行すると以下のようになるよ。

    $ scala FunctionExample.scala
    y=6
    y=7

FunctionExample.scalaで定義した関数は、`calculate`。
引数に数値を与えると、その引数に5を足して返す関数だ。
これは、`y=x+5`という一次関数を表してるんだよ。


誤解を恐れずに言うと、Cの関数やJavaのメソッド
と同様に__処理を表す部分__でもある。
もちろん違いはあるので、関数型言語の特徴と言う形で述べていこう。

# 関数型言語の特徴

- immutable (いみゅーたぶる)
- 副作用がない
- 関数はファーストクラス(第一級)

関数型言語の特徴を調べると、上記のような項目が必ず出てくる。
最初はよくわからないよね？
でも基本だから避けては通れないよ。

## immutable(いみゅーたぶる)

immutableとはim(in) + mutableのことだ。
mutable？「変わる」ことだよ。immutable「変わらない」ことだね。
「変わる」って何が？変わるのは値だよ。

Scalaでこれを端的に表すキーワードが存在している。
`var`と`val`だ。

```Mutable.scala
object Mutable{
  def main(args: Array[String]){
    var mutable = "Mutable"
    printf("%s ", mutable)

    mutable = "Change mutable"
    printf("%s ", mutable)
  }
}
```

実行すると、`var`で定義した変数`mutable`の値が切り替わることがわかるね。
これがmutableだ。

    $ scala Mutable.scala
    Mutable
    Change mutable

次にimmutable。

```Immutable.scala
object Immutable{
  def main(args: Array[String]){
    val immutable = "Immutable"
    printf("%s ", immutable)

    immutable = "Change immutable"
    printf("%s ", immutable)
  }
}
```

実行するとコンパイルエラーが発生する。

    $ scala Immutable.scala
    Immutable.scala:6: error: reassignment to val
    immutable = "Change immutable"
              ^
    one error found

immutable、即ち`val`で定義した変数の値が変えられないことがわかったかな？

## 副作用がない
本来するべきことを作用とすれば、作用に伴って別のことをしてしまうのが副作用だ。

風邪をひいたらどうする？
風邪薬を飲むよね。飲んだら眠くなることない？
風邪薬では、風邪を治すことが作用、眠くなることが__副作用__だ。

副作用の具体例をソースで表してみるよ。

```SideEffect.scala
object SideEffect{
  var total = 0
 
  def main(args: Array[String]){
    var add = (x:Int) => {
      total+=x
      total
    }
  
    printf("total=%s \n", add(1))
    printf("total=%s \n", add(1))
    printf("total=%s \n", add(1))
  }
}
```

実行すると以下のようになる。

    $ scala SideEffect.scala
    total=1
    total=2
    total=3

この例では、メソッド`add`を引数`1`で3回呼んでいるが、
呼ばれるたびに`total`を足している。

そのため、`add`は呼ばれるたびに異なる戻り値を返す。
`add`はオブジェクトフィールド`total`にも作用していることを、
副作用と言う。

副作用のない例は以下となる。

```NoneSideEffect.scala
object NoneSideEffect{
  def main(args: Array[String]){
    var add = (x: Int) => x + 5
    
    printf("add=%s \n", add(1))
    printf("add=%s \n", add(1))
    printf("add=%s \n", add(1))
  }
}
```

    $ scala NoneSideEffect.scala
    add=6
    add=6
    add=6

`SideEffect.scala`はオブジェクト指向ぽく書いたけど、
まさしくオブジェクト指向は副作用の塊だね。

もちろん関数型言語を駆使すれば、副作用を全て排除できるわけではないよ。
IOに関わる部分は副作用だからね。
でもなくせる場所では副作用をなくそうぜ！

## 関数はファーストクラス(第一級)
ファーストクラス(第一級)とは、関数を型として扱えるってことなんだ。
文字列型とか数値型とかと同じにみなせる。
型として扱えるということは、`var add`みたいな変数に、関数を設定することが可能なんだよ。
JavaScriptの`var func = function(){......};`と同じだね。

次にファーストクラスの利点。
- 関数の引数として渡せる
- 関数の戻り値として返せる

Javaにはできないことだよ。メソッドだけをオブジェクトとして返せないからね。
メソッドはオブジェクトありきなんだ。

関数の戻り値の例で見てみよう。

```FirstClassFunction.scala
object FirstClassFunction{
  def main(args: Array[String]){
    val add = (x: Int) => {
      val _add = (y: Int) =>  y + 5
      _add(x)
    }

    printf("add=%s \n", add(1))
    printf("add=%s \n", add(2))
    printf("add=%s \n", add(1))
  }
}
```

実行してみよう！

    $ scala SideEffect.scala
    add=6
    add=7
    add=6

関数`add`の戻り値はなんと関数`_add`だ！
変数`func`には、`add()`の戻り値`_add`が入っている。
そして`func(1)`は`_add(1)`を評価することと同じになる。
だから`func(1)`の結果は6になるのさ。

ちなみにファーストクラスのクラスは、オブジェクト指向のクラスとは
全く関係ないから注意してね！

__最上級だ!!!__

言語の翻訳ではよく「functions as first-class citizens」って言葉が出てきて
「第一級市民である関数」なんて訳されているよ。

# 関数とメソッドの違い

Java等のオブジェクト指向言語を使っていると、関数とメソッドの違いがわからないかもしれない。

メソッドはあくまでオブジェクトと関連付いているんだ。
オブジェクトの操作をメソッドと言う。

オブジェクトには状態(フィールド)があるんだけど、
状態によって戻り値が変わる。引数がなくても、
戻り値が変わることがあるんだ。

staticおじさんの作りしかしらなかったら、ゴメンナサイ！

一方関数は、引数に依存する。
引数が同じなら常に同じ戻り値を返し、
引数が変わったら別の戻り値を返す。
状態には依存させないよ。

文法上の違いもあるよ。

`def`キーワードはメソッドになる。

    def add(x:Int, y: Int) = x + y

これは関数リテラルで、関数となる。

    var add = (x:Int, y:Int) => x + y

# まとめ
今回は関数型言語について語ってみたけど難しかったかな？

実は僕も、関数型言語を理解するために日々悩んでいるんだ。
それだけ難しい概念だと思うけど、
ここを掌握できればプログラミングの質が上がると信じているよ。

今回の、関数型言語のソースを実際に動かすことで、

__体で感じてくれたかな？__