先日、Scala CLI v1.0.0がついにリリースされた。これまではv0系列だったので、満を持しての正式版リリースだ。おめでとう!
いちおう説明しておくとScala CLIは総合的なScalaのコマンドラインツールで、以下のようなことができる:
- Uber JAR(単体で動作するJARファイル)の生成
- GraalVMを使ったバイナリの生成
- Scala Nativeを使ったバイナリの生成
- REPL
- Scala Scriptの実行環境
このように多彩な機能を持つScala CLIは、現在のscala
コマンドを置換して将来的なscala
コマンドになることが決まっている。
さて、リリースノートによればScala CLIではv1.0.0からScala 3.3.0をデフォルトで利用することになった。Scala 3.3.0にはいくつもの修正や追加機能が含まれているが、今回はその中でもfewerBracesの標準搭載について学ぼう。
fewerBraces
fewerBracesとはこれまではDotty(Scala3系コンパイラのシリーズ名)の追加機能として提供されていたもので、率直に言えばこれまでbraceを使っていたメソッド引数をコロンを使って書けるようにするというものだ。仕様としてはSIP-44という名で呼ばれている。
具体的には、以下のような記法が可能となる(可能になるというだけで従来の中括弧も当然使える):
// 九九を生成 val xs: Seq[Int] = Seq(1, 2, 3, 4, 5, 6, 7, 8, 9) xs.zip(xs).map: (x, y) => x * y
見ての通り、メソッド引数に値(関数)を渡す箇所がコロンを使ってインデントしつつ書けるようになっている。この記法は以下のコードと等価だ:
// 九九を生成 val xs: Seq[Int] = Seq(1, 2, 3, 4, 5, 6, 7, 8, 9) xs.zip(xs).map{ (x, y) => x * y }
今回は単純な例なので不適切かもしれないが、fewerBraces記法によって中括弧が1つ削減されていることが分かると思う。Scalaでは関数も値の1つなので、メソッド引数に関数を渡すということが非常に当然に行なわれる。例えば標準ライブラリのコレクションメソッドでは、map
やfoldLeft
、traverse
など、関数を取るメソッドは枚挙に暇がない。fewerBraces機能はこうした高階関数を使う負担を減らす機能として位置付けられる。
これまでのDottyではfewerBraces記法は実験的機能の位置付けであり、特殊なimport
を使わなければ有効化することができなかった:
import language.experimental.fewerBraces
Scala 3.3.0以降では、このimport
がなくともfewerBraces記法が有効化され、どこでも使うことができるようになる。
ところで、brace、つまり中括弧を省略する記法としては既にクラス等で使われるOptional Braces記法があったが、Scala 3.3.0ではこれを更に推し進めた形となる。 どうもこの中括弧を省略して書き味をRubyやPythonに近付けようという設計の方向性にはScala作者のOdersky先生の意向があるようで、元々のOptional Braces記法もOdersky先生の発議で実装されていて、今回のfewerBraces記法の標準化もOdersky先生によるもの(ちなみにどちらのIssue/PRでもdownvoteのほうが多いので、賛否両論ある機能という位置付けである)である。古いScalaユーザは関数型言語に親しみを覚えているユーザが多いからか、あまりオフサイドルールの導入に積極的ではない雰囲気があるようだ*1。一方Odersky先生は一貫して「誰にでも広く使われる関数型言語じゃなきゃ無意味」というスタンスを取り続けていて、だからこそScalaを作ったとも言えるのだが、動的型付け言語やスクリプティング言語利用者を取り込みたいという強い狙いがあるようだ。
ちなみにパースがやりにくいのでOptional Braces記法はEmacsのscala-modeではうまく動かないようだ・・・。Optional/Fewer Braces機能は、それを使うことによって明らかに可読性が良くなるような箇所に絞って利用することが望ましいと思う。
あわせて読みたい
*1:オフサイドルールを導入するとbracesを使ったパースができないのでパースがやりにくくなる