S-JIS[2010-12-12/2015-09-22] 変更履歴

Scalaリテラル

Scalaのリテラルのメモ。

リテラルとは、型(クラス)の個々の値(を直接表現する形式)。


数値のリテラル

数値関連のリテラル。


(クラス)
説明
Int 255 数字を並べるとInt型。
表現できる範囲(Math.MIN_INT〜MAX_INT、32bit整数)を超えるとエラー。
0377 「0」から始めると八進数。
Scala2.10で非推奨になった。[2013-06-08]
0xff 「0x」または「0X」から始めると十六進数。
Long 255L
0377L
0xffL
255:Long
Intと同様の書き方で、末尾に「L」または「l(小文字)」を付けるとLong型。
表現できる範囲(Math.MIN_LONG〜MAX_LONG、64bit整数)を超えるとエラー。
Double 1.0 小数点付きの数値はDouble型。
(「0」から始まっていても十進数として認識される)
1. 末尾が小数点で終わる書き方はScala2.10で非推奨になった。[2013-06-08]
1d
1.0d
数値の末尾に「D」または「d」を付けてもよい。
1e2
2e-1
100.0
0.2
指数を指定する形式。「men」は、m×10n
Float 1.0f
1f
1e2f
2e-1f
1:Float
Doubleと同様の書き方で、末尾に「F」または「f」を付けるとFloat型。
Byte 123.toByte
123.asInstanceOf[Byte]
123:Byte
val v:Byte = 123
どの形式でも、コンパイルされたJavaでは直接byte型として扱われる。
(暗黙変換用のラッパークラスが作られたりはしない)
ただし、表現できる範囲(Math.MIN_BYTE〜MAX_BYTE、8bit整数)を超える場合、
toByte・asInstanceOfは下位1バイト分の値となるが、「:Byte」ではエラーとなる。
Short 123.toShort
123.asInstanceOf[Short]
123:Short
val v:Short = 123
どの形式でも、コンパイルされたJavaでは直接short型として扱われる。
(暗黙変換用のラッパークラスが作られたりはしない)
ただし、表現できる範囲(Math.MIN_SHORT〜MAX_SHORT、16bit整数)を超える場合、
toShort・asInstanceOfは下位2バイト分の値となるが、「:Short」ではエラーとなる。
BigInt BigInt(123)
123:BigInt
任意精度の整数
BigDecimal BigDecimal(1.0)
1:BigDecimal
1.0
1
任意精度の固定小数
BigDecimal(1, 2) 0.01 第2引数がnの場合、×10-n
Boolean true
false
Booleanのリテラルはtrue・falseのみ。

文字・文字列のリテラル

文字列関連のリテラル。


(クラス)
説明 備考
String "abc"
"abc\ndef"
文字列はダブルクォーテーションで囲む。
「\n」等のエスケープ文字が解釈される。
 
"""C:\temp\zzz.txt"""
"""\d+\.\d*"""
ダブルクォーテーション3つで囲むと、生文字リテラルとなる。
「\」はエスケープ文字として解釈されず、普通の文字として記述できる。
Windowsのファイルのパスや正規表現を書くのに便利。
ただし「u」から始まるファイル名やディレクトリー名(「\」の直後に「u」が来るの)はUnicodeエスケープとして解釈されるので要注意。
生文字リテラルはJavaには無い機能。
"""abc
def"""
生文字リテラルでは、文字列の途中で改行しても、その改行が有効となる。
"""abc\u000adef""" 生文字リテラルでも、「\u」で始まるUnicodeエスケープは解釈される。
s"abc${変数}zzz" 文字列の補間機能。Scala2.10以降。[2015-09-22]  
Char 'a' 文字はシングルクォーテーションで囲む。  
Symbol 'aaa シングルクォーテーションで始めるとシンボルになる。 シングルクォーテーションの直後にスペースを入れる事は出来ない。[2011-02-07]
また、数字から始めることも出来ない。

XMLリテラル

XMLのリテラル。[2011-02-11]

型(クラス) 説明 備考
scala.xml.Elem <tag attr="value">text</tag> Scalaでは、XMLを直接記述することが出来る。 ボディー部に波括弧でブロックを作り、
その中にScalaの式を書くことも出来る。

タプルのリテラル

タプル関連のリテラル。

型(クラス) 説明 備考
Unit () 要素数が0個のタプル。 Tuple0というクラスは無いが、Unitがそれに該当するらしい。
Unitの値は「()」しか無い。
Tuple1 Tuple1(1) 要素数が1個のタプル。  
Tuple2 (1,2)
1 -> 2
1 → 2
Pair(1,2)
Tuple2(1,2)
要素数が2個のタプル。 「->」「→」はPredefで定義されているメソッド。
PairはPredefで定義されているオブジェクト。
Tuple3 (1,2,3)
Triple(1,2,3)
Tuple3(1,2,3)
要素数が3個のタプル。 TripleはPredefで定義されているオブジェクト。
Tuple4 (1,2,3,4)
Tuple4(1,2,3,4)
要素数が4個のタプル。  

配列・コレクション等のリテラル

配列やコレクション(リスト・マップ等)関連のリテラル。

型(クラス) 説明
配列 Array(1,2,3)
Array("a","b")
 
リスト List(1,2,3)
List("a","b")
 
セット Set(1,2,3)
Set("a","b")
 
マップ Map(1->"one", 2->"two") 「->」はタプルを作るメソッド。

オブジェクトのリテラルを生成する仕組み


オブジェクトのリテラル(ファクトリー)

ArrayやList等のリテラル生成では、実際にはシングルトンオブジェクトのapply()メソッドが呼ばれている。

Java的な見方からすると、Arrayクラスのインスタンスを作るなら「new Array(1,2,3)」という形になると思う。
しかしScalaのArrayのリテラルは「new」抜きで「Array(1,2,3)」と書く。
前者はArrayクラスのコンストラクターを呼ぶ形式だが(実際のArrayクラスには値の羅列を受け取るコンストラクターは無い)、
後者はArrayオブジェクトapply()メソッドを呼ぶ形式となっている。
Scalaでは「apply」という名前のメソッドは呼び出し時にメソッド名を省略できるので、「Array.apply(1,2,3)」が「Array(1,2,3)」と書ける。

object Array 〜 {

  //引数の型に応じたapply()メソッドが用意されている(オーバーロードされている)
  def apply(x: Int, xs: Int*): Array[Int] = {
    val array = new Array[Int](xs.length + 1)
    array(0) = x
    var i = 1
    for (x <- xs.iterator) { array(i) = x; i += 1 }
    array
  }

}
scala> Array(1,2,3)
res1: Array[Int] = Array(1, 2, 3)

scala> Array.apply(1,2,3)
res2: Array[Int] = Array(1, 2, 3)

Scalaでは、「Factory」の名の付いたクラス(インスタンス生成用のクラス)を作るのではなく、シングルトンオブジェクトのapply()メソッドを使うのが一般的らしい。


関数リテラル

Scalaでは、関数もリテラルにすることが出来る。[2010-12-25]
つまり、123という数値リテラルをIntの変数に代入したりメソッドの引数にしたりできるのと同様に、
関数リテラルを関数の変数に代入したりメソッドの引数にしたりすることが出来る。
(→関数の型

通常の関数(名前の付いた関数)は、以下のように記述する。

	def 関数名(引数:型, …) : 戻り型 = 本体
	def 関数名(引数:型, …)          = 本体

関数リテラルは、これに対応して、以下の様になる。(「リテラル」なので、名前(関数名)が無い)

	(引数:型, …) => 本体 : 戻り型
	(引数:型, …) => 本体
備考
scala> (n: Int) => { n + 1 } : Int
res1: (Int) => Int = <function1>

scala> (n: Int) => { n + 1 }
res2: (Int) => Int = <function1>

scala> (n: Int) => n + 1
res3: (Int) => Int = <function1>
scala> (m:Int, n:Int) => { m + n }
res4: (Int, Int) => Int = <function2>

scala> (m:Int, n:Int) => m + n
res5: (Int, Int) => Int = <function2>
scala> () => { println(123) }
res6: () => Unit = <function0>

scala> () => println(123)
res7: () => Unit = <function0>
関数リテラルの例。
戻り値の型を省略すると、型推論によって関数本体の型と同じになる。
(というか、普通は省略する)
scala> (n: Int) => { n + 1 } : Long
res21: (Int) => Long = <function1>
scala> (n: Int) => n + 1 : Long
res22: (Int) => Long = <function1>
戻り値の型を関数本体の型から変えてみた例。
(これは、例えばREPL上で123:Long」だけ書いても通るので、“関数リテラルの戻り型の指定方法”というわけでは無さそう)
scala> ((n: Int) => { n + 1 })(123)
res23: Int = 124
scala> ((n: Int) => n + 1)(123)
res24: Int = 124
scala> ((n:Int) => { n + 1 }: Double)(123)
res27: Double = 124.0
関数リテラルを呼び出してみる例。
普通の関数を呼び出すのと同様に、関数リテラルの後ろに丸括弧を付けて引数(値)を指定する。
scala> val f = (n:Int) => n + 1
f: (Int) => Int = <function1>

scala> f(123)
res28: Int = 124
関数リテラルを変数に入れて、それを呼び出す例。
scala> var f = (n:Int) => n + 1
f: (Int) => Int = <function1>

scala> f = (n) => n + 1
f: (Int) => Int = <function1>

scala> f = n => n + 1
f: (Int) => Int = <function1>
代入先の変数の型(関数の引数の型)が分かっている場合は、関数リテラルの引数の型を省略できる。
また、この場合、引数が1個しか無いのであれば、丸括弧も省略できる。
scala> var f = (n:Int) => { n + 1 }
f: (Int) => Int = <function1>

scala> f = { _ + 1 }
f: (Int) => Int = <function1>

scala> f = _ + 1
f: (Int) => Int = <function1>
代入先の変数の型(関数の引数と戻り値の型)が分かっている場合は、関数リテラルの引数部分(丸括弧と「=>」)を省略できる。
ただし、変数を使っている場合は(変数宣言部分が省略されてしまうので)変数名も消えてしまう。
この場合、関数本体の中で「_」(プレースホルダー(placeholder))を使うことができ、変数名の代わりになる。
※引数が0個の関数リテラルの場合は引数部分を省略できない(通常の式の評価(演算)と区別できない為か?)
scala> var f = (a:Int, b:Int) => { a + b }
f: (Int, Int) => Int = <function2>

scala> f = { _ + _ }
f: (Int, Int) => Int = <function2>
引数が2つ以上ある場合でも関数本体の中でプレースホルダー「_」を使うことが出来る。
この場合、最初の「_」は最初の引数に対応し、次の「_」は次の引数に対応し…n番目の「_」はn番目の引数に対応する。
引数の順序を変えて使ったり同一の引数を複数回使ったりする事は出来ない。
また、引数の個数より少ない回数の「_」しか使わないことも出来ない。
(全ての引数を順番通りに必ず1回ずつ使う必要がある)
scala> var f = (a:Int, _:Int, _:Int) => { a }
f: (Int, Int, Int) => Int = <function3>

scala> f = (a:Int, _, _) => { a }
f: (Int, Int, Int) => Int = <function3>

scala> f = (a, _, _) => { a }
f: (Int, Int, Int) => Int = <function3>
使わない引数がある場合は、引数名に「_」を付けることが出来る。
scala> def test(f: (Int)=>Int) = { f(123) }
test: (f: (Int) => Int)Int

scala> test((n:Int) => { n + 1 })
res41: Int = 124

scala> test((n) => { n + 1 })
res42: Int = 124

scala> test( n => { n + 1 })
res43: Int = 124

scala> test((n) => n + 1)
res44: Int = 124

scala> test(n => n + 1)
res45: Int = 124

scala> test({ _ + 1 })
res46: Int = 124

scala> test(_ + 1)
res47: Int = 124
メソッドの引数に関数リテラルを渡す例。

左記のtestメソッドは、「Intを受け取ってIntを返す関数」を受け取る。
そのtestメソッドの引数に、色々な形式で関数リテラルを記述してみた。(色々省略できる)

Scala目次へ戻る / 技術メモへ戻る
メールの送信先:ひしだま