ScalikeJDBCのFirst exampleを読むための知識（２）

# はじめに
Scala の文法なのか、ScalikeJDBC固有の文法なのかを切り分けるために、まずはScala固有の文法で知っておきたいコードを紹介します。  

# 1.string interpolation （文字列補間）
Scalaでは、変数宣言した変数名を文字列内で指定して、実行時に値を入れ替える事ができます。

例）

```scala
var name = "Sam"
println(s"Hello, ${name}")
> Hello, Sam
```

\\${name}の箇所に"値"が出力されます。
2行目のs""の文字列内${name}は、最初の行で宣言したnameの値で置き換えられます。  
変数と文字列リテラルを"+"でつなぐ必要なく、変数を文字列内で利用できます。

詳しくは以下をご参照ください。
[Scala Doc:  string interpolation （文字列補間）](http://docs.scala-lang.org/ja/overviews/core/string-interpolation.html)

# 2.implicit （暗黙）
Scalaにはコードを書かなくても、別のところで宣言したコードを意識せずに呼び出す事が可能です。
First Exampleで利用しているのは、 implicit parameter（暗黙のパラメータ）です。
引数を明記しなくても、まるで記述してあるかのように関数を呼び出す事ができます。

例）

```scala
implicit val implicitMsg:String = "暗黙の教え"  

def printImplicit(implicit x: String) = println(x)

printImplicit
>暗黙の教え
```

本来は printImplicit を呼び出すときに引数が必要ですが、ここでは省略しています。
・引数定義の際(implicit x: String)にimplicitを指定
・implicit宣言した変数（implicit val implicitMsg:String）が同一スコープ内に存在する
と、引数が適用された関数を実行する事ができます。

この文法を利用する事で、SQL実行時にDBのセッション情報を毎回渡さなくても実行する事ができます。
execute.apply()は、実は、
execute.apply()(implicit session: DBSession)と定義されています。
(applyに『()』が２つあるのは『カリー化』と呼ばれるもの)
"implicit val" 宣言をスコープ内で宣言しておく事で、実行時にパラメータを明記しなくてもよくなっています。

First exampleの他のapplyも同様の形式です。


# ３.関数リテラル
foreachやmapの括弧内で使われている『（引数）=>（本体）』が関数リテラルです。
関数リテラルは代入したり、引数に渡したりする事ができます。

例）

```scala
List("Alice", "Bob", "Chris") foreach { name =>
  println(name)
}
```

リテラルの意味がとらえにくいかもしれませんが、"関数"を"値として直接宣言"したものが関数リテラルです。
上記例では、 foreach と言う関数に、 "『nameと言う引数』を『標準出力に出力する』関数"が宣言されています。


# 4 map / foreach
Scalaの学習を進めると、コレクションが多数出現します（ListとかSeqとか）。
そのコレクションを操作する際の関数が同一名称(map,foreach, ・・・)で提供されています。
例えば、
・map関数は引数の関数リテラルを実行して、結果のコレクションを返す。
・foreach関数は引数の関数を実行するが、結果を返さない。
と言った関数が存在し、それぞれの機能はどのコレクション（List、Map、Seq etc）でも存在します。

以下コードの例です。

例）

```scala
val tempList_map = List("Alice", "Bob", "Chris") map { name =>
  " Hello " + name + "!"
}
println(tempList_map)
>List( Hello Alice!,  Hello Bob!,  Hello Chris!)
```
map関数では名前の前に Hello が付与された文字列のコレクションが返されます。

例）

```scala
val tempList_foreach = List("Alice", "Bob", "Chris") foreach { name =>
  " Hello " + name + "!"
}
println(tempList_foreach)
>()
```

foreach では、何も返されません。 Unit型が返されます(Javaで言うvoidみたいなもの)。

# 5.type parameter
Javaで言う所のジェネリクスです。コレクション等に含まれる値の型が保証されます。
下記の例では、Listに含まれる値の型をStringやIntegerで指定した例です。

◯　・・・　val names : List[String] = List("test","test2")
◯　・・・　val numbers : List[Integer] = List(123,654)
×　・・・　val numbers2 : List[Integer] = List(123,654,"456")

最後の例は、Integer型のListに文字列を含んでいるためコンパイルエラーになります。



# 6.collection
ふたつ前でコレクションで良く利用する関数の紹介をしましたが、ここではコレクションそのものの紹介です。
沢山のコレクションが提供されていますが、代表的なものを３つ紹介します。

・Seq ・・・ 要素の順番を保持したコレクションです（trait）。
・List ・・・　Seqの孫クラスで順序が保証されたコレクションです。
・Map ・・・ キーと値のコレクション

Scalaでは、頻繁にList（リスト）クラスを見かけます。JavaのArrayList的なイメージ考えると "Add"で要素が追加できそうですが、追加できません。
追加する時には『::』を使います。

例）

```scala
val names : List[String] = List("test","test2")
val names2 =  "test3" :: names
println(names2)
>List(test3, test, test2)
```

# 7.apply / unapply
Scalaの文法としては、apply/unapplyは特殊な関数として定義されています。
・apply ・・・ オブジェクトでapply を省略して、『()』とコーディング可能な関数。
・unapply ・・・ 値を分割して、オブジェクトを生成する関数。

例）

```scala
object Japanese {
  def apply(firstName: String, lastName: String) = s"${firstName} ${lastName}"
  def unapply(jpName: String): Option[(String, String)] = {
    var splitChar = jpName split " "
    if(splitChar.length == 2) Some(splitChar(0), splitChar(1)) else None
  }
}

val jpManApply = Japanese("鈴木", "一郎")
val jpManUnapply = Japanese.unapply("佐藤 次郎")
println(jpManApply)
println(jpManUnapply)
> 鈴木 一郎
> Some((佐藤,次郎))
```

applyは省略して記述できており、unapplyは自動的に姓名が半角スペースで分割されています。

なお、ScalikeJDBCでは、頻繁にapplyが呼ばれます。ScalikeJDBCでは、SQL文を『実行』する際に呼ばれます。
sql"XXXX".execute.apply()
や
sql"XXXX".update.apply()
と言った具合です。


# 8.case class（ケースクラス）
ケースクラスはJavaのBeanとかDtoとか呼ばれるクラス定義の、Getter/Setterを記述しなくてもフィールドが簡単に定義可能なクラスです。更に、オブジェクト同士の比較にも便利な仕組みが用意されています。
これがcase class（ケースクラス）です。  

例

```scala
case class Student(firstName : String, lastName: String, schoolYear: Int)
// new 無しで、下記のようにインスタンスを生成できます。
val taro = Student("太郎","大阪",6)
```

”case class”を宣言することで、"apply / unapply"で紹介したコンパニオンオブジェクトのapplyメソッドが実装されます。

# 9.Option型
値が"有るか"、"無いか"を表現できる型です。
・値が存在する場合： Some[x]
・値が存在しない場合： None

Some[x]は"type parameter"で紹介した内容です（xは任意の型）。

例えばデータベースからデータを取得するメソッドにて、結果が"取得出来たか"、"取得出来なかった"のかを表現できます。  
Scalaでは、何かしらの値を取得する際に、結果が無い場合にデフォルト値を設定可能なメソッド "getOrElse(デフォルト値)"が推奨されているようです（単純なgetよりも）。  

例

```scala
val studentNo1:Option[Student] = Some(Student("太郎","大阪",6))
val studentNo2:Option[Student] = None
val classA = List(studentNo1,studentNo2)
for(s <- classA) println(s.getOrElse(Student("-","-",999)))
>Student(太郎,大阪,6)
>Student(-,-,999)
```

この例では、classAの2番目の要素は存在しません（None）。
そのため、標準出力する際に、getOrElseを利用して、Noneの場合にはデフォルト値を出力しています。
存在しない場合の処理を記述して、NullPointerExceptionを無くすことができます。


---
以上が、Scalaの文法の簡単な紹介となります。
ここで出てきた内容と次回紹介する内容を読めば、切り分けができるようになり、ScalikeJDBCの理解が深くなればいいな。