Scalaとは、プログラミング言語の一つである。
概要
Scalaとは、Javaの開発者の一人であるMartin Odersky氏が開発したオープンソースの静的型付けプログラミング言語である。Java仮想マシン上で動作するプログラムを生成できるいわゆるJVM言語である。かつては.Net Framework上でも動作したらしいが、その機能はなくなった。
導入事例としては、TwitterのインフラがScalaで書かれているというのが最も有名だが、ニコニコ動画のシステムにも一部Scalaで書かれている部分があるとのこと。
命名の由来
命名の由来は2つあり、一つはscalable languageに由来する。関数型プログラミングとオブジェクト指向の融合により、小さなプログラムの作成から、大規模開発にまで対応できるというコンセプトを表す。
もう一つの由来はイタリア語の階段を意味する単語である。これは開発者Martin Odersky氏が所属していたスイス連邦工科大学 (EPFL)にある螺旋階段にちなんだものらしい。Scalaのロゴはこの螺旋階段がモチーフになっている。
特徴
- コンパイルして生成されるのは、Java仮想マシン(JVM)上で動作する中間バイトコードである。
- オブジェクト指向と関数型プログラミングを組み合わせたプログラミング言語である。
- コンパイルしなくても対話型で実行できる環境(REPL)もある。
長所
- Javaでうまく行かなかった点を改善して設計されている。
- Javaが動く環境ならプラットフォームに依存せず動作する。
- Javaよりもコードが短くて済む。
- Javaで書かれたライブラリはそのまま使用できる。
- Play Framework, Apache Sparkなど、Scalaにネイティブ対応するものも出てきている。
- 実行速度はJavaにひけをとらないとのこと。
短所
- 使用人口が少ないので、情報も少ない。
- 玄人受けする仕様を増やした結果、プログラミング初心者にはとっつきにくいものとなった。
- 現在も発展中なので、互換性を保てない言語仕様変更がある可能性も捨てきれない。
- コンパイルが遅い。プロジェクトの規模にもよるが、しばしば分単位に及び無視できない遅さらしい。
- 当然だが、Java仮想マシンの仕様による制限を受けるし、Javaよりも最新のJava仮想マシンへの対応が遅れる。
- 求人が非常に少ない。なお供給がそれ以上に少ないからか平均年収は2015年の国内ランキング1位。
Scalaz
公式ではないがScalazというライブラリがある。モナドをはじめとする圏論由来のクラスや関数などをScalaで使用可能にするもので、多くはHaskellから移植されている。定義する記号演算子もHaskellと共通しているので、このライブラリとScalaの省略記法を使用するとかなりHaskellっぽいコードが書ける。
Java仮想マシン用にHaskellのコードを書きたい場合のHaskell実装についてはHaskellの記事を参照のこと。
Dotty(Scala 3.x)
言語設計者のMartin Odersky氏が新規に作りなおしたScalaのコンパイラで、2015年10月23日にDotty自身のコードをDottyでコンパイルするBootstrapに成功。2021年5月14日リリースのScala 3.0以降でコンパイラに採用されている。
名前の由来はScalaの中核をなす型システムに関する理論であるDOT Calculus(DOTはDependent Object Typesの略で"."とは関係ない)だと思われる。余談だがDOT Calculusによる型の健全性についてはCoqによる定理証明がなされている
。
Scala 2.x系のコンパイラscalacより高速に動作するとのことだが、2.x系の言語仕様とは一部互換性がない。また、Pythonのようにブロックを中括弧でなくインデントで表現する記法が導入されるなど、コーディングスタイルにも変更が行われている。
Typesafe → Lightbend
Scalaの後援企業にMartin Odersky氏が2011年5月に設立したTypesafe社がある。同社は2015年5月に社名変更を発表し、2016年3月から社名がLightbendとなった。
関連動画
関連商品
もう少し具体的な特徴
どうしてもJavaとの比較になってしまいがちにはなるが、言語仕様上の長所と短所を(やや細かいが)もう少し具体的に記述してみる。総じていうと、毎日コードを書く人には便利な機能が備わっている一方で、たまにしか使わない規則でも忘れてしまうとコードが読めなくなる、という感じ(個人の感想です)。
もう少し具体的な長所
- Javaのようなプリミティヴ型は存在しないので、IntもStringもすべて統一的に扱うことができる。
- 演算子(実際にはメソッド名)を定義できるので、数量を表すオブジェクトでも"add"のようなメソッドを使わずに四則演算の記号を用いて計算することができる。
- ヒアドキュメントを使ってエスケープシーケンスなしで文字列リテラルを記述できる。
- 型推論により、変数宣言時の型の記載が省略できることが多い。
- イミュータブルなプログラミング方式を記述しやすいように、valによる宣言(Javaは変数宣言にfinalをつけると記述が冗長になるが、Scalaはvarとvalで同じ長さで宣言できる)のような言語仕様やコレクションのライブラリ(指定しないとイミュータブルなコレクションになる)なども含めて設計されている。
- implicitにより定義されていれば、自動で型を変換してくれる。
- 比較は.equals()メソッドでなく、"=="で行える。
- 行末にセミコロンがいらない;
- 関数が複数の値を返したいときは、新しい型を定義しなくても、タプルを使えばOK。
- ラムダ式が使えることが大きな利点だったが、Java8からはJava側にラムダ式が導入されたため、この点はあまり違いがなくなった。
- Javaの単一継承による不自由さを、traitというものを新設して多重継承を事実上可能にしている。もっとも、Java8からはもともと多重継承(implements)可能であったインターフェイスに、実装内容を含めることができるようになったため、この点でも差は少なくなった。
- Optionクラスの導入によりぬるぽに悩まされることはなくなった。Java8では類似のOptionalがあるものの、後付けであるためライブラリでの導入が進んでおらず、Scalaのライブラリ群の方が対応が進んでいる。
- オブジェクト指向でも関数型の流儀でもプログラミングできるので、どちらのプログラマーでも抵抗なく参入できる。
もう少し具体的な短所
- 記号をメソッド名に使用可能にしたため、"++:"のようなぱっと見ただけではよくわからないメソッドがコレクションや並列処理などでも頻繁に使われる。
- implicitにより、知らない間に型が変換されていることがある。このためAPIドキュメントを探すときに、黙示変換された先まで探さないと見つからないことがある。
- 型の宣言に限らずいろいろ省略できるので、書くときは楽でも読むときは省略箇所を補う知識や能力がいる。
- 省略の組み合わせ方によっては一筋縄では理解できないことも。
- 多重継承を事実上認めたせいで継承関係が複雑になり、APIドキュメントから継承されたメソッドを追いかけるのが困難になった。たとえばListひとつとっても(ScalaとJavaでは位置づけがやや異なるものの)、Javaでは継承しているものは直接・間接あわせて2つだけ
なのに対し、Scalaでは直接継承しているものだけで7つの継承元
が存在する。
- 繰り返し処理を再帰を用いて書くために末尾再帰最適化が可能になっているが、必須ではないものの@tailrecアノテーションの使用が推奨される。ループ処理はすでに末尾再帰最適化されたメソッドで処理することが多いとはいえ、繰り返し処理が煩雑なのはマイナスポイントになると思われる。
- Javaでは実装の隠蔽が奨励されるケースも多いが、遅延評価になるかとか末尾再帰になっているかどうかなども含めて実装内容を考えにいれないといけない場合が少なからずある。
- 一部のライブラリはJavaの標準ライブラリを使用するようになっており、Javaのライブラリを使っているのかScalaのライブラリを使っているのかで混乱しやすい。
- Javaを見ているとstaticメソッドをわざわざクラスのメンバーに含める必要が無いのではという考えが頭をよぎることがないわけではないが、実際にScalaのコンパニオンオブジェクトのようにクラスと同名のシングルトンオブジェクトというものに分離されると、それはそれで違和感があったりする。
- 例外処理がすべて非チェック例外になる。Scalaは例外の処理はOptionやEitherでするので問題ないのだろうが、Javaのクラス由来の例外までcatchを保証しないのは、Javaが前提としている安全機構を無視することであり、危険なことに思える。
- オブジェクト指向でも関数型の流儀でもプログラミングできるので、オブジェクト指向のプログラマーが、関数型プログラマーの書いたコードをメンテナンスしなければならなくなった時に非常に苦労する。あるいはその逆。
関連項目
関連リンク
関連生放送
ScalaMatsuri 2016: 期限未定でタイムシフト放送中
。
- 0
- 0pt