先日、下記のようなツイートに接した。
えっと、つまり何が言いたかったんだっけ……そうそう、Scala怖くないよって話だった。
— ney (@tom_myz_) 2018年8月14日
書き慣れると快適だし、学習コストの割に単価がだいぶん違ったりもする(した)のでJavaやってる人はまじで気軽にチャレンジするといいとおもう
Scalaについては、以前参加したイベントで、コアメンバー(?)らしき方から強く推薦されて、面白そうだなと感じていた。
Scalaというと、JavaやHaskelなどから影響を受けており、JVM上で動く言語だ。冒頭のツイートがそうであるように、Java経験者であれば手を出しやすい(連携できるからという側面もあろうが)というような話を目にすることがある。
僕にとってJavaは、最近は仕事でもプライベートでも書く機会はないが、新人研修でじっくり勉強することのできた言語であり、実際のプロジェクトで書いた唯一の言語でもある。
というわけで、Scalaの勉強を始めてみることにした。関数型のプログラミングを勉強したことがないので、そのあたりも学ぶことができればと思っている。
入門〜環境構築〜Hello World
Scalaに入門しようと思って調べ始めると、下記の記事にまず行き当たった。この手の、情報を集約してくる種類の記事は、自分はおそらく書かないと思うが、存在していると助かることが多いので、それぞれの分野の有識者の方々にはぜひ書いていただきたい。
その中から、評判の良さそうなものということで、ドワンゴさんの新人研修向け資料をまずは読み進めてみることにした。
「新人エンジニア向けの研修資料」という位置付けではあるが、僕が受けた新人研修のように「プログラミング全く未経験」向けのものではないらしい。
読者層としては、
- 大学の情報学部卒である
- Java言語の基本知識がある
- 何か意味のあるアプリケーションを作ったことがある
- 趣味でTwitter APIなどを触ったり、プログラミングを行っている
人(相当)を仮定しています。なお、上記の指標はこの資料を読むにあたってのあくまで目安であり、特に大学の情報学部卒でなければ理解できないといったことはありません。ただし、本資料は1つ以上のプログラミング言語でアプリケーションを作れることを最低限の前提にしていますので、その点留意ください。
環境構築〜Hello World
環境の構築は、もともとJDKが入っていたので、sbtとIntellij IDEAのみインストールした。この辺りは、研修資料がスクショ付きで非常に丁寧に書かれているので、悩むことなく進めることができた。
テキストに従い、REPLで簡単な出力と計算を行ってみる。まずはお決まりのHello World。
println("Hello World")
なるほどJavaを思い出す。ここのところはずっとconsole.log()
だったので、少し懐かしい。四則演算も、特に違和感は持たない。
ここまではよくあるプログラミング入門という感じ。JavaScriptをかじったので、var命令だって怖くない(意味は違うが)。
制御構文の多くが「式」である?
しかし、制御構文の章に入って、雲行きが怪しくなる。
まず、「構文」と「式」と「文」についての説明が入るのだ。プログラミング経験者向けの資料なので、「条件分岐が必要だから〜〜」とif文の説明に入るわけではないのは自然だが、式と文の違いを意識させることに意外の念を持った。制御構文の章の冒頭に置かれたこの説明の末尾には、以下のような記述がある。
ScalaはCやJavaなどの手続き型の言語に比べて、文よりも式になる構文が多いです。 Scalaでは文よりも式を多く利用する構文が採用されています。これにより変数などの状態を出来るだけ排除した分かりやすいコードが書きやすくなっています。
式になる構文が多いと言いながら、この章で出てくるのはどいつもこいつも式である。下記すべて、Javaにも存在するものだが、Javaでは文(つまり、値を持たない)であるのに対し、Scalaでは式(つまり、値を持つ)であるという。
{}
if
while
for
特に、for
については、Javaのfor
文におけるのとは異質な使い方をすることができるようである。
実は、
for
構文はyield
キーワードを使うことで、コレクションの要素を加工して返すという全く異なる用途に使うことができます。特にyield
キーワードを使ったfor
式を特別に for-comprehensionと呼ぶことがあります。
これらが式であるということは、おそらく、関数型プログラミングにとって重要な特徴なのではないだろうか。これから勉強を進めていく中で、明らかになるだろう。
match式、パターンマッチ
制御構文の章の後半は、match
式の導入である。Javaのswitch
が引き合いに出されているが、かなり申し訳程度であると感じた。Javaのswitch
は、(OOPの立場からは)隙あらばポリモフィズムによる書き換えの対象となるような代物だ。それに対して、Scalaにおけるmatch
は、極めて強力な機能を持っているようだ。
match
式の説明の部分は、下記のような項目に分けられている。
- パターンをまとめる
- パターンマッチによる値の取り出し
- 中置パターンを使った値の取り出し
- 型によるパターンマッチ
- JVMの制約による型のパターンマッチの落とし穴
説明に一通り目は通したが、どうにも頭に入ってこない。正直に言って、この段階で既にJavaとだいぶ違うというので少々面食らっている。先達(この方も元々Javaプログラマで、Scalaを後から勉強された方だったと思う)も、下記のようにツイートしていて、どうも関門のようだ(このツイートで言われているのはもっと高度な話だと思うが)。
関数型の考え方とか圏論とかは実際そこまで苦しんだ覚えなくて、地味にfor式とパターンマッチングがなかなか使いこなせなかった思い出。ここタプル使えるんだっけ?とか、コンパイルエラーに苦しんだ結果括弧の形変えたら治ったとか。
— ney (@tom_myz_) 2018年8月14日
思ったこと
上にも既に書いたが、ここまでJavaと違うとは思わなかった。いや、違うというのはわかっていたが、違いが出てくるのが思ったより早かった。JavaScriptはよく、「Javaと名前は似ているけど全然違う」と言われるが、JavaScriptを勉強し始めたときとは全くレベルの異なる戸惑いを感じている。
とはいえ、言語として違いがあるということは、それだけに学ぶことの意義も大きいということだ。自分がオブジェクト指向をマスターしているとは口が裂けても言えないが、それとは違うパラダイムを学ぶことは意味のあることだと確信できるし、何より面白い。
ボブおじさんも、下記のように言っている。オブジェクト指向と関数型プログラミングの両方を身に付けることは、単にプログラマとしての幅を広げたり、書き方の参考にすることができるようになったりというだけでなく、両方を駆使したプログラミングを可能にするということなのかもしれない。
参照透過性(=再代入をしないこと)を本質とする関数的プログラミング(FP)と、呼ぶ側ソースの呼ばれる側のソースへの依存なしに動的ポリモフィズムの利用することを本質とするオブジェクト指向(OO)は直交している。ゆえに排他的ではなく両立できるし、両立すべきだ!という話。 https://t.co/lnYjraIR9O
— こまど (@ky_yk_d) 2018年4月14日