Scala の改行

Scala言語のreferenceを読んでいたら結構びっくりだったので書いておこう.

C系の言語では,改行はスペースと等価で基本的に意味を持たない.文字列の途中でもない限り,どこに改行を入れても大丈夫.Javaも分布的にはC系なので同じ.これがPython になると行とインデントに強い意味がある.

で,Scalaの文法はブロックの書き方がCっぽいので,なんとなく改行の扱いも同じような感じかと思ったら全然そんなことはなかった.C系の言語では';(セミコロン)'を文のターミネータにしている.ところが,Scalaでは';'が省略でき,改行をターミネータにすることができる.このため話がややこしくなっているようだ.以下言語仕様の1.2より.

Scalaでは以下の条件が満たされた場合に,改行が特殊なトークン'nl'として扱われる.

  1. 直前のトークンが文のターミネータであり得る
  2. 直後のトークンが文の開始であり得る
  3. 複数の文が許される場所に現れている

なんだか曖昧で嫌な感じ.

結果こんなことになる.下の例は,無名クラスの宣言として解釈される.

new Iterator[Int] 
{ 
  private var x = 0 
  def hasNext = true 
  def next = { x += 1; x } 
} 

ところが,改行を追加すると,オブジェクトの生成と,ローカルブロックの2つの文として解釈される.

new Iterator[Int] 

{ 
  private var x = 0 
  def hasNext = true 
  def next = { x += 1; x } 
} 

うーん...なんかわかりにくいなあ.改行1つと改行2つ以上で意味が変わるなんて,なんかtexみたいだ...

他の例.これはカレー化された関数.

def func(x: Int) 
   (y: Int) = x + y 

こちらだとエラー.

def func(x: Int) 

   (y: Int) = x + y

所感

余分な改行は,Cの習慣でつい入れてしまいがちな気がする.';'をオプショナルにしなければ,こんなややこしいことにならなかったんじゃないだろうか.どうしてわざわざ省略したがるんだろう.うてばいいのに,';'ぐらい.