yoshikit1996’s diary

日々勉強したことの備忘録です。

Scalaの型について(Scalaスケーラブルプログラミング読書メモ1)

型が重要な感じがしたのでメモ.

静的な型づけ

静的型付け言語であるScalaでは,ジェネリクスで型をパラメータ化したり,抽象型で型の詳細を隠蔽することができる.型が動的な言語(PythonRubyとか)では,ジェネリクスや抽象型などの仕組みはなくとも,上記のようなことができる.そのため,Scalaジェネリクスや抽象型を使用することは煩わしく感じられることもあるが,静的な型には様々なメリットが存在する.

静的な型付け言語では,プログラム実行より前に型が決まっている.プログラム実行前に型に関する情報がわかるため,次のようなメリットをもたらす.

検証可能性

静的な型システムはある種のランタイムエラーが存在しないことを証明できる.

例えば,次のようなコードの場合,コンパイル時にエラーが判明する.(IDEであれば,赤線を引いてくれる)

val convertToString = (num: Int) => num.toString()
println(convertToString(true))

他にもプライベートなメソッドに外部からアクセスしていないかどうかや,関数に渡した引数の数が正しいかどうか等がプログラム実行前にわかる. (あからさまなエラーだと,動的型言語でもIDEが検出してくれるが,少し複雑なプログラムになると,検出できないはず)

一方で,動的な型付け言語では,プログラム実行前に検証しづらいため,しっかりテストを書く習慣があるらしいが, 最初から検証しやすい静的型付け言語を使えばよい気がする.

リファクタリング安全性

静的な言語で書かれたプログラムをリファクタリングする際,コンパイルが通るかどうかを確認することにより,変更内容が正しいかどうか検証することができる. (コンパイルが通ったからといって,プログラムにバグがないことを証明できるわけではないが...)

IDEのアシスト

静的型付け言語で書かれたプログラムをIDEで変数名やメソッド名を補完したり,リファクタリングをしたりする際,IDEのアシストが強力である.

新しい型を作れる

Scalaのクラスでは*-などの演算子を実装できる.そのため,ネイティブサポートがあるかのように感じられる.

高水準な型システム

Javaで大文字が文字列に含まれているかどうかをチェックする際,ループで文字を1文字ずつ処理する必要があり,低水準なことを考慮しながらプログラムを書く必要がある.

// Java
boolean nameHasUpperCase = false;
for(int i = 0; i < name; ++i){
  if(Character.isUpperCase(name.charAt(i))){
    nameHasUpperCase = true;
    break;
  }
}

対して,Scalaでは述語関数(条件を満たした場合に真、または偽を返す関数)で高水準にコードを書くことができる.ここでnameは紛れもなくJavaのStringクラスだが,必要に応じてStringOpsにラップ(暗黙変換)される.

// Scala
val nameHasUpperCase = name.exists(_.isUpper)

この例では,本来低水準なもの(JavaのStringクラス)を高水準なもの(String + StringOps)として扱うことができ,さらにそれを組み込み型であるかのように扱えている.