Sök…


Anmärkningar

Den här funktionen finns i Scala 2.10.0 och senare.

Hej String Interpolation

S- interpolatorn tillåter användning av variabler i en sträng.

val name = "Brian"
println(s"Hello $name")

skriver "Hej Brian" till konsolen när den körs.

Formaterad stränginterpolering med f-interpolatorn

val num = 42d

Skriv ut två decimaler för num med f

println(f"$num%2.2f")
42.00

Skriv ut num med vetenskaplig notation med e

println(f"$num%e")
4.200000e+01

Skriv ut num i hexadecimal med a

println(f"$num%a")
0x1.5p5

Andra formatsträngar finns på https://docs.oracle.com/javase/6/docs/api/java/util/Formatter.html#detail

Använda uttryck i strängbokstäver

Du kan använda lockiga hängslen för att interpolera uttryck i strängbokstäver:

def f(x: String) = x + x
val a = "A"

s"${a}"    // "A"
s"${f(a)}" // "AA"

Utan hängslen skulle scala bara interpolera identifieraren efter $ (i detta fall f ). Eftersom det inte finns någon implicit omvandling från f till en String detta ett undantag i detta exempel:

s"$f(a)"  // compile-time error (missing argument list for method f)

Anpassade stränginterpolatorer

Det är möjligt att definiera anpassade stränginterpolatorer utöver de inbyggda.

my"foo${bar}baz"

Utvidgas av kompilatorn till:

new scala.StringContext("foo", "baz").my(bar)

scala.StringContext har ingen my metod, därför kan den tillhandahållas genom implicit konvertering. En anpassad interpolator med samma beteende som det inbyggda s interpolatorn skulle då beräknas enligt följande:

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
  }
}

Och interpolationen my"foo${bar}baz" skulle desugar till:

new MyInterpolation(new StringContext("foo", "baz")).my(bar)

Observera att det inte finns några begränsningar för interpoleringsfunktionens argument eller returtyp. Detta leder oss ner på en mörk väg där interpolationssyntax kan användas kreativt för att konstruera godtyckliga objekt, som illustreras i följande exempel:

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

Stränginterpolatorer som extraktorer

Det är också möjligt att använda Skalas stränginterpoleringsfunktion för att skapa utarbetade extraktorer (mönstermatchare), som kanske mest känt används i de kvasiquotes API för Scala-makron.

Med tanke på att n"p0${i0}p1" desugars till new StringContext("p0", "p1").n(i0) är det kanske inte förvånande att extraktorfunktionalitet är aktiverad genom att tillhandahålla en implicit omvandling från StringContext till en klass med egenskap n av en typ som definierar en unapply eller inte unapplySeq .

Som ett exempel kan du tänka på följande extraktor som extraherar sökvägsegment genom att konstruera ett regelbundet uttryck från StringContext delarna. Vi kan sedan delegera det mesta av det tunga lyftet till den unapplySeq metod som tillhandahålls av den resulterande 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 _ => ???
}

Observera att path också kan definiera en apply för att fungera som en vanlig interpolator också.

Rå stränginterpolering

Du kan använda den råa interpolatorn om du vill att en sträng ska skrivas ut som den är och utan att undgå literaler.


println(raw"Hello World In English And French\nEnglish:\tHello World\nFrench:\t\tBonjour Le Monde")

Med användning av den råa interpolatorn bör du se följande tryckt i konsolen:


Hello World In English And French\nEnglish:\tHello World\nFrench:\t\tBonjour Le Monde

Utan den råa interpolatorn skulle \n och \t ha undgått.


println("Hello World In English And French\nEnglish:\tHello World\nFrench:\t\tBonjour Le Monde")

Grafik:


Hello World In English And French
English:       Hello World
French:        Bonjour Le Monde


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow