Scala Language
Interpolacja ciągów
Szukaj…
Uwagi
Ta funkcja istnieje w Scali 2.10.0 i nowszych.
Witaj, interpolacja ciągów znaków
Interpolator s pozwala na użycie zmiennych w ciągu znaków.
val name = "Brian"
println(s"Hello $name")
wyświetla „Hello Brian” na konsoli po uruchomieniu.
Sformatowana interpolacja ciągu przy użyciu f interpolatora
val num = 42d
Wydrukuj dwa miejsca dziesiętne dla num
za pomocą f
println(f"$num%2.2f")
42.00
Wydrukuj num
za pomocą notacji naukowej za pomocą e
println(f"$num%e")
4.200000e+01
num
w systemie szesnastkowym za pomocą a
println(f"$num%a")
0x1.5p5
Inne ciągi formatu można znaleźć na https://docs.oracle.com/javase/6/docs/api/java/util/Formatter.html#detail
Używanie wyrażenia w literałach łańcuchowych
Za pomocą nawiasów klamrowych można interpolować wyrażenia na literały łańcuchowe:
def f(x: String) = x + x
val a = "A"
s"${a}" // "A"
s"${f(a)}" // "AA"
Bez nawiasów klamrowych interpolowałby identyfikator po znaku $
(w tym przypadku f
). Ponieważ nie ma niejawnej konwersji f
na String
jest to wyjątek w tym przykładzie:
s"$f(a)" // compile-time error (missing argument list for method f)
Niestandardowe interpolatory ciągów
Oprócz wbudowanych można zdefiniować niestandardowe interpolatory ciągu.
my"foo${bar}baz"
Został rozszerzony przez kompilator do:
new scala.StringContext("foo", "baz").my(bar)
scala.StringContext
nie ma my
metody, dlatego można ją zapewnić przez niejawną konwersję. Niestandardowy interpolator z samego zachowania jak wbudowanych s
interpolatora by następnie być realizowane w następujący sposób:
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
}
}
A interpolacja my"foo${bar}baz"
sprowadziłaby się do:
new MyInterpolation(new StringContext("foo", "baz")).my(bar)
Zauważ, że nie ma ograniczeń co do argumentów ani typu zwracanego przez funkcję interpolacji. To prowadzi nas na ciemną ścieżkę, gdzie składnię interpolacji można twórczo wykorzystać do budowy dowolnych obiektów, jak pokazano w poniższym przykładzie:
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
Interpolatory łańcuchowe jako ekstraktory
Możliwe jest również użycie funkcji interpolacji ciągów Scali do tworzenia skomplikowanych ekstraktorów (dopasowań wzorców), co być może najbardziej znane jest w quasi - cytatowym API makr Scali.
Biorąc pod uwagę, że n"p0${i0}p1"
desuguje się do new StringContext("p0", "p1").n(i0)
, być może nic dziwnego, że funkcja ekstraktora jest włączona poprzez zapewnienie niejawnej konwersji z StringContext
na klasę z Obiekt n
typu definiowania unapply
lub unapplySeq
metody.
Jako przykład rozważmy następujący ekstraktor, który wyodrębnia segmenty ścieżki, konstruując wyrażenie regularne z części StringContext
. Następnie możemy przekazać większość ciężkiego podnoszenia do metody unapplySeq
dostarczonej przez wynikowy scala.util.matching.Regex :
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 _ => ???
}
Zauważ, że obiekt path
może również zdefiniować metodę apply
, aby zachowywał się również jako zwykły interpolator.
Interpolacja ciągów nieprzetworzonych
Możesz użyć surowego interpolatora, jeśli chcesz, aby napis był drukowany tak, jak jest i bez ucieczki literałów.
println(raw"Hello World In English And French\nEnglish:\tHello World\nFrench:\t\tBonjour Le Monde")
Za pomocą interpolatora typu raw w konsoli powinny zostać wyświetlone następujące informacje:
Hello World In English And French\nEnglish:\tHello World\nFrench:\t\tBonjour Le Monde
Bez surowego interpolatora \n
i \t
zostałyby usunięte.
println("Hello World In English And French\nEnglish:\tHello World\nFrench:\t\tBonjour Le Monde")
Wydruki:
Hello World In English And French
English: Hello World
French: Bonjour Le Monde