String interpolation in scala 2.10

@tototoshi

interpolation
【名】

    〔他のものに〕挿入すること、差し挟むこと
    〔原文の〕改ざん、不正な改変
    〔付け加えられた〕語句、挿入句
    《数学》補間、内挿

簡単に言うと、文字列の中に変数を埋め込めるってこと

ruby でよくあるやつ

age = 10
puts "Bob is #{age} years old" #> Bob is 10 years old

scala では(今まで)

scala> val n = 10
n: Int = 10

scala> "Bob is " + n + " years old"
res0: String = Bob is 10 years old

scala では(これから)

scala> val n = 10
n: Int = 10

scala> s"Bob is $n years old"
res2: String = Bob is 10 years old

format もできる

scala> f"Bob is $n%03d years old"
res4: String = Bob is 010 years old

正体

scala> val n = 10
n: Int = 10

scala> s"Bob is $n is years old"
res0: String = Bob is 10 is years old

scala> new StringContext("Bob is ", " is years old").s(n)
res1: String = Bob is 10 is years old

文字列が、StringContext というオブジェクトに変換され、そのメソッドを呼んでいる

変換パターン

id ”text0${ expr1 }text1 … ${ exprn }textn”
id ”””text0${ expr1 }text1 … ${ exprn }textn”””

StringContext(”””text0”””, …, ”””textn”””).id(expr1, …, exprn)

拡張できる

scala> implicit class URLEncodedStringContext(s: StringContext) {
     |   def url(params: Any*) = {
     |     if (params.isEmpty) {
     |       ""
     |     } else {
     |       var res = ""
     |       for (i <- (0 until s.parts.size - 1)) {
     |         res += s.parts(i)
     |         res += java.net.URLEncoder.encode(params(i).toString, "utf-8")
     |       }
     |       res += s.parts.last
     |       res
     |     }
     |   }
     | }
defined class URLEncodedStringContext

拡張できる

scala> val akiba = "秋葉原"
akiba: String = 秋葉原

scala> url"encoded: ${akiba}"
res0: String = encoded: %E7%A7%8B%E8%91%89%E5%8E%9F

kwsk

SIP11