Scala Language
Stränginterpolering
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