Scala Language
Interpolazione a stringa
Ricerca…
Osservazioni
Questa funzione esiste in Scala 2.10.0 e versioni successive.
Hello String Interpolation
L'interpolatore s consente l'utilizzo di variabili all'interno di una stringa.
val name = "Brian"
println(s"Hello $name")
stampa "Ciao Brian" sulla console quando è in esecuzione.
Interpolazione di stringhe formattate usando l'interpolatore f
val num = 42d
Stampa due cifre decimali per num
usando f
println(f"$num%2.2f")
42.00
Stampa num
usando la notazione scientifica usando e
println(f"$num%e")
4.200000e+01
Stampa num
in esadecimale con a
println(f"$num%a")
0x1.5p5
Altre stringhe di formato possono essere trovate su https://docs.oracle.com/javase/6/docs/api/java/util/Formatter.html#detail
Utilizzo dell'espressione in stringhe letterali
Puoi usare parentesi graffe per interpolare espressioni in stringhe letterali:
def f(x: String) = x + x
val a = "A"
s"${a}" // "A"
s"${f(a)}" // "AA"
Senza le parentesi, scala interpolerebbe solo l' identificatore dopo $
(in questo caso f
). Poiché non vi è alcuna conversione implicita da f
a una String
questa è un'eccezione in questo esempio:
s"$f(a)" // compile-time error (missing argument list for method f)
Interpolatori di stringhe personalizzati
È possibile definire interpolatori di stringa personalizzati oltre a quelli incorporati.
my"foo${bar}baz"
Viene espanso dal compilatore per:
new scala.StringContext("foo", "baz").my(bar)
scala.StringContext
non ha il my
metodo, quindi può essere fornito dalla conversione implicita. Un interpolatore personalizzato con lo stesso comportamento come il comando incorporato s
interpolatore sarebbe quindi calcolato come segue:
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
}
}
E l'interpolazione del my"foo${bar}baz"
sarebbe stata la seguente:
new MyInterpolation(new StringContext("foo", "baz")).my(bar)
Si noti che non esiste alcuna restrizione sugli argomenti o il tipo di ritorno della funzione di interpolazione. Questo ci porta lungo un percorso oscuro in cui la sintassi di interpolazione può essere utilizzata in modo creativo per costruire oggetti arbitrari, come illustrato nel seguente esempio:
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
Interpolatori a stringa come estrattori
È anche possibile utilizzare la funzione di interpolazione delle stringhe di Scala per creare estrattori elaborati (pattern matcher), come forse il più famoso impiegato nelle API quasiquotes dei macro Scala.
Dato che n"p0${i0}p1"
desugars a new StringContext("p0", "p1").n(i0)
, forse non sorprende che la funzionalità estrattore sia abilitata fornendo una conversione implicita da StringContext
a una classe con struttura n
di un tipo che definisce una unapply
o unapplySeq
metodo.
Ad esempio, si consideri il seguente estrattore che estrae i segmenti del percorso costruendo un'espressione regolare dalle parti StringContext
. Possiamo quindi delegare la maggior parte del sollevamento pesante al metodo unapplySeq
fornito dalla scala.util.matching.Regex risultante:
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 _ => ???
}
Si noti che l'oggetto path
potrebbe anche definire un metodo apply
per comportarsi come un normale interpolatore.
Interpolazione di stringa grezza
È possibile utilizzare l'interpolatore raw se si desidera che una stringa venga stampata così com'è e senza alcuna escape di valori letterali.
println(raw"Hello World In English And French\nEnglish:\tHello World\nFrench:\t\tBonjour Le Monde")
Con l'uso dell'interpolatore raw , dovresti vedere quanto segue stampato nella console:
Hello World In English And French\nEnglish:\tHello World\nFrench:\t\tBonjour Le Monde
Senza l'interpolatore raw , \n
e \t
sarebbero stati sfuggiti.
println("Hello World In English And French\nEnglish:\tHello World\nFrench:\t\tBonjour Le Monde")
stampe:
Hello World In English And French
English: Hello World
French: Bonjour Le Monde