S-JIS[2015-09-22] 変更履歴
Scalaの識別子(クラス名やメソッド名・変数名等)のメモ。
クラス名やパッケージ名、メソッド名・変数名等のことを識別子と呼ぶ。
Scalaでは、(Javaと同じく)半角英数字・アンダースコア「_」や、いわゆる全角文字が識別子として使える。
(識別子を数字で始めることは出来ない)
(アンダースコア1文字のみでは識別子として使用できない)
また、Scalaでは「+」や「-」といった記号も識別子として使用できる。
予約語(キーワード)として定義されている単語も、バッククォートで囲むことで使用できる。
メソッド名として使用する識別子(単語)では、applyやupdateのように、特別な役割が割り当てられているものもある。
→特殊なメソッド名
Scalaでは、「+」や「-」といった記号も識別子として使用できる。
主にメソッドとして定義することで、中置記法を使って式のように記述することが可能になる。
case class Hoge(val n: Int) { def +(other: Hoge) = Hoge(n + other.n) } scala> println(Hoge(123) + Hoge(456)) Hoge(579)
→記号を使ってメソッドを定義した場合の演算の優先順位
→記号を使って識別子を定義した場合のJavaでの名前
ただし、ピリオド「.
」やコロン「:
」セミコロン「;
」といった、Scalaの文法上で使用されている文字は使用できない。
これらの記号でもバッククォートで囲めば使用できるが、あまり綺麗ではない^^;
class `.` { def `.` = "." } scala> println(new `.`().`.`) .
ちなみに、「+」や「-」も変数名として定義できるが、使う場面では演算子としての解釈が優先されるようなので、実際には使えない。
scala> val + = 123 +: Int = 123 scala> println( + ) <console>:1: error: illegal start of simple expression println( + ) ^
ただしこれが駄目なのは、「+」や「-」が別の場所で単項演算子として定義されているから、単項演算子のみが指定されたように見える為。
単項演算子と変数を並べる書き方(「+1」のような)だと使える。
scala> println(+ +) 123 scala> println(- +) -123
単項演算子でない「*」や「/」は使うことが出来る。
scala> val * = 10
*: Int = 10
scala> println(*)
10
scala> println(* * *)
100
scala> println(***)
<console>:8: error: not found: value ***
println(***)
^ ←空白を入れないと、まとめて1つの識別子として判断されるので、エラー
まぁ、見てのとおり訳が分からなくなるので、変数名としては記号は使わない方がいいだろうね^^;
なお、アンダースコア「_」1文字のみだと、識別子として使用できない。
scala> class _ <console>:1: error: identifier expected but '_' found. class _ ^
scala> class `_` <console>:1: error: wildcard invalid as backquoted identifier class `_` ^
scala> val _ = 123 <console>:5: error: wildcard invalid as backquoted identifier lazy val $result = `_` ^ <console>:10: error: wildcard invalid as backquoted identifier + "_: Int = " + scala.runtime.ScalaRunTime.replStringOf(`_`, 1000)
scala> val `_` = 123 <console>:1: error: wildcard invalid as backquoted identifier val `_` = 123 ^
Scalaではアンダースコア1文字「_」はワイルドカード等に使っているので、識別子として使えないようになっているのだろう。
Scalaの予約語となっている単語でも、識別子(クラス名やパッケージ名、メソッド名・変数名)として使用することが出来る。[2010-12-07]
例えばmatchやyieldはScalaの予約語(特別な意味・文法を持つ単語)なので、そのまま使うとコンパイルエラーになる。
scala> val match = 1 <console>:1: error: illegal start of simple pattern val match = 1 ^ scala> Thread.yield() <console>:1: error: identifier expected but 'yield' found. Thread.yield() ^ ↑「identifier」は識別子(ここではメソッド名)のこと。つまり「識別子が来るはずなのに予約語yieldを見つけたぞ」というコンパイルエラー
こうした場合に単語をバッククォート「`」でくくると、識別子として扱われる。
scala> val `match` = 1 match: Int = 1 scala> Thread.`yield`()
予約語でない単語の場合、バッククォートで囲っても囲まなくても同じものとして扱われる。[2015-09-22]
scala> val `abc` = 123; println(abc) 123 abc: Int = 123 scala> val zzz = 456; println(`zzz`) 456 zzz: Int = 456
ちなみにJava(JDK1.6まで)では、予約語をScalaの様に識別子として扱う方法は無い。
なのでJDK1.4でassertという単語が新しく予約語になった際、JDK1.3でassertという識別子を使っているソースはそのままではJDK1.4でコンパイルできなかった。なので-source
1.3オプションを使ってわざわざ古いバージョンでコンパイルしてみたり…(苦)
JDK1.5でもenumで同じ問題が起きる。
JDK1.7では、新しい予約語が解釈される範囲を限定することで、そういったことが無いようになる…という噂だったが、JDK1.7では新しい予約語は追加されていない。