Scalaの制御構文(1)

# はじめに

下記のテキストを通して、基本的な書き方を学びつつ、個人的に気になったことを検証していくメモ代わりです。
https://dwango.github.io/scala_text/basic.html
本当にありがとう、dwango様・・・

# Scalaの制御構文

ざっくりまとめ

* 「構文」と「式」と「文」それぞれ使い分けよう
* `{}` 式は基本中の基本
*  if式、whileはCやPHPと同様の使用感
*  for分はifを中にぶっこめたり、yieldにより四季を生成できる

## 「構文」と「式」と「文」という用語

（今まで気にしていなかった）各種用語にかんして、ざっくりまとめ

* 構文(Syntax)
    * プログラミング言語内で特別扱いされるキーワードと正しいプログラムを構成するためのルール
* 式（Expression）
    * 評価することで値になるもの
    * `1` , `1 + 2` , `"hoge"`
* 文（Statement）
    * 評価しても値にならないもの（定義全体としては値を持たないもの）
    * `val i:Int = 1`

## `{}` 式

* 一般系

    ```scala
    { exp1; exp2; ... expN }
    ```
    * 式が改行で区切られていれば `セミコロンを省略可`
* Scalaではメソッド定義が一般的

    ```scala
    def foo(): String = {
        "foo" + "foo"
    }
    ```
    * メソッド定義の構文に特別に `{}` が含まれているわけではない
        * `{"foo" + "foo"}` という式が、メソッドに代入されているってことかな？
## if式

* 一般式

    ```scala
    if (条件式) A [else B]
    ```
* 使用方法

    ```scala
    scala> var age = 26
    age: Int = 26

    scala> if (age < 20) {
     |     "未成年"
     | } else {
     |     "年がどんどん・・・"
     | }
    res1: String = 年がどんどん・・・
    
    scala> if (age < 20) {}

    ```

## while式
* 一般式

    ```scala
    while (条件式) A
    ```
* 使用方法

    ```scala
    scala> var i = 1
    i: Int = 1

    scala> while (i <= 10) {
         |     print( i + ", ")
         |     i++
         | }
    <console>:11: error: value ++ is not a member of Int
                      i++
                       ^

    scala> while (i <= 10) {
         |     print( i + ", ")
         |     i += 1
         | }
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
    ```
    * インクリメント演算子が使えないんだという発見ｗ

## for式
* 一般式

    ```scala
    for(ジェネレータ1;  ジェネレータ2; ... ジェネレータn) A
    # ジェネレータ1 = a1 <- exp1; ジェネレータ2 = a2 <- exp2; ... ジェネレータn = an <- expn
    ```
* 使用方法
    * 通常

        ```scala
        scala> for (x <- 1 to 5; y <- 1 until 5) {
         |     print( "(" + x + "," + y + ") ")
         | }
        (1,1) (1,2) (1,3) (1,4) (2,1) (2,2) (2,3) (2,4) (3,1) (3,2) (3,3) (3,4) (4,1) (4,2) (4,3) (4,4) (5,1) (5,2) (5,3) (5,4)
        ```
        * 前述したジェネレータが内部にネストしたループのように扱われる
            * 多重ループ書く時にネストが深くならなくて使いやすそうと思った
    * if有りの使用方法

        ```scala
        scala> for (x <- 1 to 5; y <- 1 until 5 if x != y) {
             |     print( "(" + x + "," + y + ") ")
             | }
        (1,2) (1,3) (1,4) (2,1) (2,3) (2,4) (3,1) (3,2) (3,4) (4,1) (4,2) (4,3) (5,1) (5,2) (5,3) (5,4)
        ```
        * 条件式も後述できる
    * ifが中間のジェネレータの場合

        ```scala
        scala> for (x <- 1 to 5; y <- 1 until 5 if x != y; z <- 3 to 8) {
             |     print( "(" + x + "," + y + "," + z +") ")
             | }
        (1,2,3) (1,2,4) (1,2,5) (1,2,6) (1,2,7) (1,2,8) (1,3,3) (1,3,4) (1,3,5) (1,3,6) (1,3,7) (1,3,8) (1,4,3) (1,4,4) (1,4,5) (1,4,6) (1,4,7) (1,4,8) (2,1,3) (2,1,4) (2,1,5) (2,1,6) (2,1,7) (2,1,8) (2,3,3) (2,3,4) (2,3,5) (2,3,6) (2,3,7) (2,3,8) (2,4,3) (2,4,4) (2,4,5) (2,4,6) (2,4,7) (2,4,8) (3,1,3) (3,1,4) (3,1,5) (3,1,6) (3,1,7) (3,1,8) (3,2,3) (3,2,4) (3,2,5) (3,2,6) (3,2,7) (3,2,8) (3,4,3) (3,4,4) (3,4,5) (3,4,6) (3,4,7) (3,4,8) (4,1,3) (4,1,4) (4,1,5) (4,1,6) (4,1,7) (4,1,8) (4,2,3) (4,2,4) (4,2,5) (4,2,6) (4,2,7) (4,2,8) (4,3,3) (4,3,4) (4,3,5) (4,3,6) (4,3,7) (4,3,8) (5,1,3) (5,1,4) (5,1,5) (5,1,6) (5,1,7) (5,1,8) (5,2,3) (5,2,4) (5,2,5) (5,2,6) (5,2,7) (5,2,8) (5,3,3) (5,3,4) (5,3,5) (5,3,6) (5,3,7) (5,3,8) (5,4,3) (5,4,4) (5,4,5) (5,4,6) (5,4,7) (5,4,8)
        ```
        * 記述可能
    * 定義されてなくて、きっとだめだろうと思うやつ

        ```scala
        scala> for (x <- 1 to 5 if x != y; y <- 1 until 5; z <- 3 to 8) {
             |     print( "(" + x + "," + y + "," + z +") ")
             | }
        <console>:8: error: not found: value y
                      for (x <- 1 to 5 if x != y; y <- 1 until 5; z <- 3 to 8) {
                                               ^
        ```
        * ですよね
    * Listを使用した出力

        ```scala
        scala> for(e <- List("A", "B", "C", "D", "E")) println(e)
        A
        B
        C
        D
        E

        scala> for(e <- List("A", "B", "C", "D", "E")) print(e + ", ")
        A, B, C, D, E,
        ```
    * yieldを使用

        ```scala
        scala> for(e <- List("A", "B", "C", "D", "E")) yield {
             |   "Pre" + e
             | }
        res8: List[String] = List(PreA, PreB, PreC, PreD, PreE)
        ```
        * yield：産する、もたらす、生む、引き起こす
        * コレクションの要素を加工して返す（新規に生成してくれるやつ）
    * 数値の場合はどうなる？

        ```scala
        scala> for (x <- 1 to 5; y <- 1 until 5) yield {
             |     x + "," + y
             | }
        res9: scala.collection.immutable.IndexedSeq[String] = Vector(1,1, 1,2, 1,3, 1,4, 2,1, 2,2, 2,3, 2,4, 3,1, 3,2, 3,3, 3,4, 4,1, 4,2, 4,3, 4,4, 5,1, 5,2, 5,3, 5,4)

        scala> for (x <- 1 to 5; y <- 1 until 5) yield {
             |     x + y
             | }
        res10: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 3, 4, 5, 3, 4, 5, 6, 4, 5, 6, 7, 5, 6, 7, 8, 6, 7, 8, 9)
        ```
        * 普遍のcollectionで返してくれる
        * 型は自動生成される
        * でも、vectorだから、自分で定義できないのかな？
            * 調査した感じ、ジェネレータの型で自動で変換するらしいので、型はジェネレータで指定が無難？
    * とりあえず、ジェネレータで色々試す

        ```scala
        scala> for (x <- List(1 to 5); y <- 1 until 5) yield {
             |     x + y
             | }
        <console>:9: error: type mismatch;
         found   : Int
         required: String
                          x + y
                              ^

        scala> for (x <- List(1 to 5); y <- List(1 until 5)) yield {
             |     x + y
             | }
        <console>:9: error: type mismatch;
         found   : scala.collection.immutable.Range
         required: String
                          x + y
                              ^

        scala> for (x <- List(1 to 5); y <- List(1 to 5)) yield {
             |     x + y
             | }
        <console>:9: error: type mismatch;
         found   : scala.collection.immutable.Range.Inclusive
         required: String
                          x + y
                              ^
        scala> for (x <- List(1 to 5); y <- List(1 to 5)) yield {
             |     x + "," + y
             | }
        res15: List[String] = List(Range(1, 2, 3, 4, 5),Range(1, 2, 3, 4, 5))

        scala> for (x <- List(1,2,3); y <- List(4,5,6)) yield {
             |     x + y
             | }
        res16: List[Int] = List(5, 6, 7, 6, 7, 8, 7, 8, 9)

        scala> for (x <- List(1,2,3); y <- List(4,5,6)) yield {
             |     x + "," + y
             | }
        res17: List[String] = List(1,4, 1,5, 1,6, 2,4, 2,5, 2,6, 3,4, 3,5, 3,6)
        ```
        * toやuntilを使用すると、Range型になるので、直接的な結合は変換後じゃないと難しそう
            * 今後、型変換に関して学んだ上で追記したいところ