コンパイラによる型推論、アクターによる並列処理、パーサコンビネータ、Javaライブラリを直接取り扱える等、魅力的な言語Scalaを勉強しているのだが、忘れっぽい自分用の学習メモを付けることにした。
個人的な感想としては慣れないうちは、Scalaのコードは非常にわかりにくい。
なぜなら関数定義だけで数多くの省略形が用意されている上、カリー化された関数なんかは、一見Scala組み込みのAPIのようにも見えたりする。
一般的な関数の定義は次のようになる。
def someFunction (arg1:Int, arg2:String) : String = { //なんか巻数の処理 }
defに続くのが関数名、その後ろのカッコには引数とその型をコロンで区切って宣言、複数の引数がある場合はカンマで区切る。
カッコの後ろはこの関数の戻り値の型を宣言していて、その後ろのイコールはこの関数に戻り値があることを明示する。
続く波カッコ内に関数の内容を書く…まぁこの辺はアリがち。
関数の内容からコンパイラが戻り値の型を推測できる場合は関数の型宣言を省略できる。
def someFunction (arg1:Int, arg2:String) = { if(arg1 < 0) arg2 else "bigger than 0!" }
関数の内容が1文だけの場合は波カッコを省略できる。
そろそろ関数の定義じゃなくて、ただの代入式っぽくなってきたぞ…。
def someFunction (arg1:Int, arg2:String) = if(arg1 > 0) arg2 else "bigger than 0!"
また、Class内のgetterメソッドとして、単純に値を返すだけの場合、
def getProperty = classval
とか書ける。
うん、簡潔。でも、もうパッと見は関数って感じじゃないよね。
クラスのメソッドを呼び出す場合なんかも省略形式が用意されている。
例えばmyTestクラスのfirst関数を呼ぶ場合、全部書くと次の通り。
myTest.first(1)
でもインスタンス化されたクラスの関数を呼ぶ場合は、途中のピリオドの代わりにスペースでもいいらしい…
myTest first(1)
さらに、引数が一つならカッコも省略できて…
myTest first 1
とか。カッコの省略はタイプ数を減らすって意味ではいいと思うけど、ピリオドの代わりにスペースでOKとか何が嬉しいのかよくわかりません…。
ちなみに戻り値はJavaのようにreturn xx としなくても、関数内で最後に実行された式の結果が自動的に戻り値となります。もちろん明示的にreturnを付ける事もできるのですが…そうしないのがScala流なのかな?
おかげで複雑なifを組み上げると、何が戻るのかさっぱり分からない関数が出来上がります。
(その時点でバッドコーディングなんだろうな…)
さらに、高階関数に渡すための「関数リテラル」
//高階関数からxを引数として受取り、奇数はfalse、偶数はtrueを返す関数リテラルで、「x % 2 == 0」が関数の内容になります。 (x:Int) => x % 2 == 0 //また、xの型をIntと推論できる場合は型宣言を省略でき... (x) => x % 2 == 0 //さらに引数のカッコも省略可能 x => x % 2 == 0 //でもって、関数リテラルはこんな風に高階関数に渡して使います。 List(1,2,3,4,5,6,7,8,9,10).filter(x=>x%2==0) //結果は下記のような2、4、6、8、10だけのListが出来上がります。 //res0: List[Int] = List(2, 4, 6, 8, 10)
省略形って使いこなせれば非常に便利なのですが、やりすぎるとなんのこっちゃわからなくなるんですよねー。
だからperlがキライだったりするものでして、ハイ。
さらにこれから、引数の部分適用やカリー化の概念が出てくるので、なかなか一筋縄ではいきませんねー。