Lambdaカクテル

京都在住Webエンジニアの日記です

Invite link for Scalaわいわいランド

Scala3のOptional Bracesを試してみた

ちびちびScala3に生えた新機能の実際に使ってみるチャレンジをやっている。いつの日かチームに導入できたら嬉しいね、とか、自分で使いこなせるようになると嬉しいね、というモチベーションである。

今日はOptional Bracesについて勉強した。ソースコードは以下に置いてある。

github.com

Optional Braces

Optional Bracesとは、特定の場合にブレース、つまり中括弧を省略してもよいという新機能で、Pythonとかのオフサイドルールを意識した機能のようだ。人によって好き嫌いが分かれそう。

dotty.epfl.ch

メソッド等のボディ

def run(): Unit =
  introduce()
  println("ObjectやClassなどはcolonでブロックを作る")
  println("メソッドのブロックはとくに何もつけなくてもよい")

このように、メソッドのbodyの中括弧を省略できる。同じインデントを保っていれば同じブロックとみなされるので、空行を入れることもできる。

def run(): Unit =
  introduce()
  println("ObjectやClassなどはcolonでブロックを作る")
  println("メソッドのブロックはとくに何もつけなくてもよい")

  println("ここはrunの一部とみなされる")

クラスやオブジェクト等のボディ

メソッドなどのボディと対立して、クラスなどのボディはtemplate bodyと呼ばれて区別されている。template bodyはコロンを用いて中括弧を省略できる。

case class TemplateBody(x: String):
  println("classやobject、trait、packageの中身はtemplate bodyと呼ばれ、通常のブロックとは区別されている。")
  println("このようなtemplate bodyではコロンを用いてbraceを省略できる。")

特殊な場合

基本的にこれだけである。「クラス、オブジェクト、トレイト、パッケージ」かそうでないかで覚えるとよい。前四者にはコロンが必要で、それ以外の場合には必要ない。

さらに特定の場合にはより丁寧な使い方ができるようになっている。

case文ではインデントしなくてもいい

val FooRx = """(foo)""".r.unanchored
"foofoofoo" match
case FooRx(s) => println("前段のmatchと同列のインデントが許可されている。")
case otherwise => ???
println("caseでない文が来た時点でmatchが終わったものとみなされる。")

match式ではインデントすることもできるが、インデントせず同列にcaseを書くこともできる。おそらく見易さを意識した措置であろう。そのうち紹介するであろうenumでも同様の措置となっている。

endトークンを用いて見易くできる

オフサイドルールを適用するとき、メソッドが長大になると著しく読解困難になるという問題がある。これを見越してか、以下のような構文が使えるようになっている。

def foo()
  println("endトークンを置いてもよい")
end foo

end 名前と覚えておけばよさそう。

Scala 3.3以降: メソッド引数の中括弧省略

Scalaにはブロックを引数に取るメソッドがたくさんあるため、このブロックの中括弧を省略できるようにする仕組みがScala 3.3から使えるようになる見込みだ。このような場合にはコロンを使ってブロックを表現する。

val xs = Seq(1, 2, 3, 4,5)
xs.map: x =>
  x * x
// equivalent
xs.map:
  x =>
    x * x

times(10):
  println("foo")

これはかなりかっこいい。サンプルには書かれていなかったが、多分caseも使えるかな?

// 使えてほしい
xs.map: case (k, v) =>
  v -> k

これができると指が腱鞘炎から守られると思う。

今日はここまで。

★記事をRTしてもらえると喜びます
Webアプリケーション開発関連の記事を投稿しています.読者になってみませんか?