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


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow