Scala Language
文字列の補間
サーチ…
備考
この機能は、Scala 2.10.0以降にあります。
Hello文字列の補間
sインターポレータは、文字列内の変数の使用を許可します。
val name = "Brian"
println(s"Hello $name")
実行時に "Hello Brian"をコンソールに表示します。
fインターポレータを使用した書式付き文字列の補間
val num = 42d
fを使用してnum
小数点以下2桁を出力する
println(f"$num%2.2f")
42.00
eを使用して科学記法を使用してnum
を出力する
println(f"$num%e")
4.200000e+01
印刷num
と16進数で
println(f"$num%a")
0x1.5p5
その他の書式文字列については、次のURLを参照してください。https://docs.oracle.com/javase/6/docs/api/java/util/Formatter.html#detail
文字列リテラルでの式の使用
中括弧を使用して式を文字列リテラルに補間することができます。
def f(x: String) = x + x
val a = "A"
s"${a}" // "A"
s"${f(a)}" // "AA"
中括弧がなければ、scalaは$
(この場合はf
)の後に識別子を補間するだけです。 f
からString
への暗黙的な変換はないので、次の例では例外です。
s"$f(a)" // compile-time error (missing argument list for method f)
カスタム文字列インターポレータ
組み込みのものに加えてカスタムの文字列インターポレータを定義することは可能です。
my"foo${bar}baz"
コンパイラによって次のように展開されます。
new scala.StringContext("foo", "baz").my(bar)
scala.StringContext
はmy
メソッドがありません。したがって、暗黙の変換によって提供できます。組み込みs
インターポレータと同じ振る舞いのカスタム補間器は、次のように実装されます。
implicit class MyInterpolator(sc: StringContext) {
def my(subs: Any*): String = {
val pit = sc.parts.iterator
val sit = subs.iterator
// Note parts.length == subs.length + 1
val sb = new java.lang.StringBuilder(pit.next())
while(sit.hasNext) {
sb.append(sit.next().toString)
sb.append(pit.next())
}
sb.toString
}
}
そして、 my"foo${bar}baz"
補間はmy"foo${bar}baz"
ようにdesugarでしょう:
new MyInterpolation(new StringContext("foo", "baz")).my(bar)
補間関数の引数や戻り値の型に制限はないことに注意してください。これは、次の例に示すように、補間構文を創造的に使用して任意のオブジェクトを構築することができる暗い道を導きます。
case class Let(name: Char, value: Int)
implicit class LetInterpolator(sc: StringContext) {
def let(value: Int): Let = Let(sc.parts(0).charAt(0), value)
}
let"a=${4}" // Let(a, 4)
let"b=${"foo"}" // error: type mismatch
let"c=" // error: not enough arguments for method let: (value: Int)Let
抽出器としての文字列補間器
Scalaマクロのquasiquotes APIで最も有名になっているように、Scalaの文字列補間機能を使って精巧な抽出子(パターンマッチャー)を作成することも可能です。
n"p0${i0}p1"
がnew StringContext("p0", "p1").n(i0)
に対応していない場合、 StringContext
からの暗黙的な変換を提供することによって抽出機能が有効になることは、 unapply
またはunapplySeq
メソッドを定義する型のプロパティn
例として、 StringContext
部分から正規表現を構築することによってパスセグメントを抽出する次の抽出プログラムを考えてみましょう。その後、大量の重い吊り上げを、結果として得られるscala.util.matching.Regexが提供するunapplySeq
メソッドに委譲できます 。
implicit class PathExtractor(sc: StringContext) {
object path {
def unapplySeq(str: String): Option[Seq[String]] =
sc.parts.map(Regex.quote).mkString("^", "([^/]+)", "$").r.unapplySeq(str)
}
}
"/documentation/scala/1629/string-interpolation" match {
case path"/documentation/${topic}/${id}/${_}" => println(s"$topic, $id")
case _ => ???
}
path
オブジェクトは、正規のインターポレータとしても動作するためにapply
メソッドを定義することもできることに注意してください。
生の文字列補間
文字列をそのまま出力し、リテラルをエスケープしない場合は、 生の補間器を使用することができます。
println(raw"Hello World In English And French\nEnglish:\tHello World\nFrench:\t\tBonjour Le Monde")
生の補間器を使用すると、コンソールに次のような出力が表示されます。
Hello World In English And French\nEnglish:\tHello World\nFrench:\t\tBonjour Le Monde
未処理の補間器がなければ、 \n
と\t
はエスケープされていました。
println("Hello World In English And French\nEnglish:\tHello World\nFrench:\t\tBonjour Le Monde")
印刷物:
Hello World In English And French
English: Hello World
French: Bonjour Le Monde