リテラルについて解説

Scala 3 (Dotty 0.26.0-RC1) 2.13.3 2.12.12
最終更新:2020年8月14日

[AD] scalapediaでは記事作成ボランティアを募集しています

リテラルとは何でしょうか?
この記事ではリテラルについて解説します。

リテラルとはソースコードに値を直接記述したもの

リテラルとはプログラムのソースコードの中に特定のデータ型の値を直接記述したものです。
例えば、ソースコードの中に記述した123は整数値のリテラル表記です。

また、多くのプログラミング言語では文字列をダブルクォーテーション(")で囲んで記述します。(例: "文字列")
このように値をソースコードの中に記述するために定められている書式もリテラルです。

Scalaで利用できるリテラル表記

Scalaでは以下のリテラル表記が使用できます。

  • 数値
  • 真偽値
  • 文字
  • 文字列
  • 関数
  • タプル

数値のリテラル表記

数値のリテラル表記には整数値と浮動小数点があります。

整数値のリテラル表記

整数値のリテラル表記はその名の通りプログラム中に記述した整数値です。

整数値は10進数または16進数で記述します。
16進数で記述する場合は整数値の前に0xをつけて記述します。

  • 10進数で記述した場合
val x = 123
  • 16進数で記述した場合
val x = 0x7b

整数値の型は以下の4つです。

  • Int
  • Long
  • Byte
  • Short

通常、プログラム中に記述した整数値はInt型の値です。

整数値の後ろにLはまたは、lを記述した場合は、Long型の値になります。
lは非推奨です。Lを利用するのが良いでしょう。

  • Intの例
val x = 123 val y = 0x7b
  • Longの例
val x = 123L val y = 0x7bL

記述したリテラルの型がByteShortのどれかに予測できて、かつ値がその型の範囲内であればその型に変換します。
以下の例では変数の型を宣言しているため指定した整数値は変数の型に変換し、変数に設定されます。

  • Byteの例
val x: Byte = 123 val y: Byte = 0x7b
  • Shortの例
val x: Short = 123 val y: Short = 0x7b

浮動小数点のリテラル表記

浮動小数点のリテラル表記はFloatまたはDoubleです。

浮動小数点は以下の方法で記述します。

  • 小数点を含む数値
val x = 123.456
  • 指数表現
val x = 1.23456e2
  • 末尾にdまたはDをつける(Double)
val x = 123d
  • 末尾にfまたはFをつける(Float)
val x = 123f

末尾に何もつけない場合はDoubleになります。

真偽値のリテラル表記

真偽値のリテラルは、Boolean型のtrueまたはfalseです。

文字のリテラル表記

文字リテラルはChar型のシングルクォーテーション(')で囲まれた単一の文字です。
指定できる文字は任意のユニコード文字です。


  • 'a', '\u0041', '\n'

また、以下のように整数値で指定することもできます。

val c: Char = 123

文字列のリテラル表記

文字列リテラルはString型のダブルクォーテーション(")で囲まれた文字のシーケンスです。
バックスラッシュ(\) + 文字で改行(\n)等のエスケープ文字を含めることができます。

println("この文字列は\n3行に分けて\n表示されます。")

以下のように文字列中の\nの位置で改行して表示されます。

この文字列は 3行に分けて 表示されます。

生文字リテラル

ダブルクォテーション(")3つで囲むと生文字リテラルになります。
生文字リテラルではバックスラッシュ(\)はエスケープ文字として扱われません。

println("""C:\Users\hogehoge\Desktop""")

以下のようにバックスラッシュ(\)がそのまま表示されます。

C:\Users\hogehoge\Desktop

また、文字列の途中で改行すると改行を含んだ文字列になります。

println("""この文字列は 3行に分けて 表示されます。""")

以下のように改行されて表示されます。

この文字列は 3行に分けて 表示されます。

上記の例では、2行目と3行目の左側の空白もそのまま文字列に含まれています。
空白を取り除きたい場合は、以下のようにstripMarginメソッドを使用します。

println("""この文字列は |3行に分けて |表示されます。""".stripMargin)

stripMarginメソッドを使用すると、以下のように2行目、3行目の左側の空白は除かれて表示されます。

この文字列は 3行に分けて 表示されます。

加工文字列リテラル

加工文字リテラルを使用すると文字列内に直接変数の参照を埋め込むことができます。
加工文字リテラルは文字列の前に特定の文字(補完子)を置くことで表現します。

Scalaでは以下の3つの補完子を提供します。

  • s補完子
  • f補完子
  • raw補完子

また、利用者が任意の補完子(カスタム補完子)を用意することができます。

s補完子

文字列リテラルの先頭にsを置くことで文字列中に変数を記述することができます。

val name = "Taro" println(s"Hello $name.")

以下のように文字列中に埋め込んだ変数「name」を評価した値が表示されます。

Hello Taro.

また、以下のように式を記述することもできます。

println(s"1 + 1 = ${1 + 1}")

式を評価した値が表示されます。

1 + 1 = 2

f補完子

文字列リテラルの先頭にfを置くことで文字列中に埋め込んだ変数の書式を指定することができます。
以下のように変数の後ろに「%書式」の形式で記述します。
省略した場合は「%s」が適用されます。
%sは文字列です。

val name = "Mt. Fuji" val height = 3776.12 println(f"$name is $height%4.1fm height.")

変数「height」は小数点以下が2桁のDoubleですが、書式では小数点以下を1桁に指定しているため、四捨五入して小数点1桁で表示されます。

Mt. Fuji is 3776.1m height.

f補完子で指定する書式はJavaの機能を使用しています。
指定できる書式の詳細は以下を参照してください。

raw補完子

「raw補完子」は文字列リテラル内に変数を埋め込むことができる点は「s補完子」と同じです。
文字列リテラル内でエスケープを実行しない点が、「s補完子」との違いです。

以下のように「s補完子」を使用した場合は文字列リテラル内の\nは改行文字に置換されます。

val name = "Hanako" println(s"Hello \n $name.")
Hello Hanako.

raw補完子の場合はも維持列リテラル内の\nは改行文字に置換されずにそのまま表示されます。

val name = "Hanako" println(raw"Hello \n $name.")
Hello \n Hanako.

カスタム補完子

前述の3つの補完子の他に利用者が独自の補完子を定義することができます。

以下の例ではカスタム補完子myを使用して値を[]で囲んで表示しています。

val x = 123 println(my"x=$x")
x=[123]

このようなことができる理由を説明します。

ダブルクォテーション(")の前に文字を記述すると、Scalaのコンパイラは該当するコードをStringContextクラスのインスタンスへのメソッド呼び出しに変換します。

前述の補完子myを使用したコードは以下のように変換されます。

new StringContext("x=", "").my(x)

もちろんStringContextクラスにはmyメソッドは存在しません。
そのため、利用者はStringContextクラスのmyメソッドを呼び出した場合の処理を追加する必要があります。
この処理はimplicitクラスを使用して記述します。

補完子myを処理するコードは以下のとおりです。

implicit class MyHelper(val sc: StringContext) extends AnyVal { def my(args: Any*): String = { val strings = sc.parts.iterator val expressions = args.iterator val str = new java.lang.StringBuffer(strings.next()) while(expressions.hasNext) { str.append("[") str.append(expressions.next().toString()) str.append("]") str.append(strings.next()) } str.toString() } }

このようにすることで利用者が独自の補完子を追加できるようにしています。

関数のリテラル表記

Scalaの関数は以下のように右辺のパラメータリストと=>、左辺の式またはブロックで構成されます。
これを関数リテラルと呼びます。

(パラメーターリスト) => 式 or ブロック

以下のSeqのメソッドの引数に関数リテラルを記述する例を見てみます。

val list = Seq(1, 2, 3, 4, 5)

以下の例ではSeqmapメソッドの引数に関数リテラルを記述しています。

val result = list.map((x: Int) => x * 2) println(result)

mapメソッドに渡す関数の引数の型は省略可能です。
これは、コンパイラによりInt型に推測可能なためです。

val result = list.map(x => x * 2) println(result)

また、引数が関数内で1度だけ使われる場合は、引数の宣言を省略することができます。

val result = list.map(_ * 2) println(result)

実行結果は以下のとおりすべて同じです。

List(2, 4, 6, 8, 10)

値を返さない場合がある関数のリテラル表記

関数リテラルの例をもう1つ紹介します。

以下の例では、Seqcollectメソッドを使用して要素のうち偶数の値を抽出しています。
collectメソッドに渡している関数は、渡された引数を2で割った結果が0(偶数)の場合のみ値を返しています。
このように値を返さない場合がある関数をPartialFunctionと言います。

val result = list.collect({case x if x % 2 == 0 => x}) println(result)

実行結果は以下のようになります。

List(2, 4)

タプルのリテラル表記

タプルとは決まった数の要素を含む値です。
以下のように要素をカッコで囲んで記述するとタプルのリテラル表記となります。

val t = (1, 2, 3, 4)

また、要素の数が2つのタプルは以下のように記載することができます。

val t = ("key" -> "value")
val t = ("key" → "value")

は非推奨なので使わないほうが良いでしょう。

Scala 3で廃止予定のリテラル表記

シンボルのリテラル表記

シンボルリテラルはシングルクォーテーション(')で始まる文字列です。
以下のように記述します。

val symbol = 'symbol

同じ名前を持つシンボルは常に同じオブジェクトを参照します。

シンボルリテラルは利用頻度が低いためScala 3で廃止されます。
シンボルリテラルは使用しないほうが良いでしょう。

XMLのリテラル表記

XMLリテラルはその名の通りXMLを表す文字列です。
Scalaではソースコード上に直接XMLを記述することができます。

val xml = <html> <head> <title>タイトル</title> </head> <body> <p>本文</p> </body> </html>

XMLリテラルを扱うためのライブラリ(scala-xml)は2.11で標準ライブラリから分離されました。
XMLリテラルを使う場合は、scala-xmlをsbtの設定ファイルに記述する必要があります。

libraryDependencies += "org.scala-lang.modules" %% "scala-xml" % "1.3.0"

また、XMLリテラル表記はScala 3で廃止されます。
Scala 3ではXMLリテラル表記の代わりに「xml補完子」が追加される予定です。
XMLリテラルは使用しないほうが良いでしょう。

サイト内検索