Scala Language
Stringinterpolatie
Zoeken…
Opmerkingen
Deze functie bestaat in Scala 2.10.0 en hoger.
Hallo tekenreeksinterpolatie
Met de s- interpolator kunnen variabelen binnen een string worden gebruikt.
val name = "Brian"
println(s"Hello $name")
drukt "Hallo Brian" af op de console wanneer deze wordt uitgevoerd.
Geformatteerde tekenreeksinterpolatie met de f-interpolator
val num = 42d
Druk twee decimalen af voor num
met behulp van f
println(f"$num%2.2f")
42.00
num
afdrukken met wetenschappelijke notatie met e
println(f"$num%e")
4.200000e+01
num
afdrukken in hexadecimaal met een
println(f"$num%a")
0x1.5p5
Andere indelingsstrings zijn te vinden op https://docs.oracle.com/javase/6/docs/api/java/util/Formatter.html#detail
Expressie gebruiken in letterlijke tekenreeksen
U kunt accolades gebruiken om expressies te interpoleren naar stringliterals:
def f(x: String) = x + x
val a = "A"
s"${a}" // "A"
s"${f(a)}" // "AA"
Zonder de accolades interpoleert scala de identifier alleen na de $
(in dit geval f
). Aangezien er geen impliciete conversie is van f
naar een String
dit een uitzondering in dit voorbeeld:
s"$f(a)" // compile-time error (missing argument list for method f)
Aangepaste stringinterpolators
Het is mogelijk om aangepaste stringinterpolators te definiëren naast de ingebouwde.
my"foo${bar}baz"
Is door de compiler uitgebreid naar:
new scala.StringContext("foo", "baz").my(bar)
scala.StringContext
heeft my
methode niet, daarom kan het worden geleverd door impliciete conversie. Een aangepaste interpolator met hetzelfde gedrag als het interne s
interpolator zou dan als volgt uitgevoerd:
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
}
}
En de interpolatie die my"foo${bar}baz"
zou willen:
new MyInterpolation(new StringContext("foo", "baz")).my(bar)
Merk op dat er geen beperking is voor de argumenten of het retourtype van de interpolatiefunctie. Dit leidt ons langs een donker pad waar syntaxis van de interpolatie creatief kan worden gebruikt om willekeurige objecten te construeren, zoals geïllustreerd in het volgende voorbeeld:
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
Stringinterpolators als extractors
Het is ook mogelijk om Scala's stringinterpolatiefunctie te gebruiken om uitgebreide extractors (patroonmatchers) te maken, zoals misschien het meest bekend in de quasiquotes-API van Scala-macro's.
Gezien het feit dat n"p0${i0}p1"
naar new StringContext("p0", "p1").n(i0)
, is het misschien niet StringContext
dat de extractorfunctionaliteit is ingeschakeld door een impliciete conversie van StringContext
naar een klasse met eigenschap n
van een type dat een unapply
of unapplySeq
methode unapplySeq
.
Beschouw als voorbeeld de volgende extractor die StringContext
extraheert door een reguliere expressie te construeren uit de StringContext
delen. We kunnen vervolgens het grootste deel van het zware werk delegeren naar de unapplySeq
methode die wordt geboden door de resulterende 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 _ => ???
}
Merk op dat het path
object kan ook bepalen een apply
methode om gedragen als normale interpolator ook.
Ruwe stringinterpolatie
U kunt de onbewerkte interpolator gebruiken als u wilt dat een tekenreeks wordt afgedrukt zoals deze is en zonder letterlijk te ontsnappen.
println(raw"Hello World In English And French\nEnglish:\tHello World\nFrench:\t\tBonjour Le Monde")
Bij gebruik van de onbewerkte interpolator zou het volgende in de console moeten worden afgedrukt:
Hello World In English And French\nEnglish:\tHello World\nFrench:\t\tBonjour Le Monde
Zonder de onbewerkte interpolator zouden \n
en \t
zijn ontsnapt.
println("Hello World In English And French\nEnglish:\tHello World\nFrench:\t\tBonjour Le Monde")
prints:
Hello World In English And French
English: Hello World
French: Bonjour Le Monde