Scala Language
Interpolación de cuerdas
Buscar..
Observaciones
Esta característica existe en Scala 2.10.0 y superior.
Hola Interpolación De Cuerdas
El interpolador s permite el uso de variables dentro de una cadena.
val name = "Brian"
println(s"Hello $name")
Imprime "Hola Brian" en la consola cuando se ejecuta.
Interpolación de cadena formateada utilizando el Interpolador f
val num = 42d
Imprime dos decimales para num
utilizando f
println(f"$num%2.2f")
42.00
Imprimir num
usando notación científica usando e
println(f"$num%e")
4.200000e+01
Imprimir num
en hexadecimal con una
println(f"$num%a")
0x1.5p5
Otras cadenas de formato se pueden encontrar en https://docs.oracle.com/javase/6/docs/api/java/util/Formatter.html#detail
Usando la expresión en cadenas literales
Puede usar llaves para interpolar expresiones en literales de cadena:
def f(x: String) = x + x
val a = "A"
s"${a}" // "A"
s"${f(a)}" // "AA"
Sin las llaves, Scala solo interpolaría el identificador después de $
(en este caso f
). Dado que no hay una conversión implícita de f
en una String
esta es una excepción en este ejemplo:
s"$f(a)" // compile-time error (missing argument list for method f)
Interpoladores de cadena personalizados
Es posible definir interpoladores de cadena personalizados además de los integrados.
my"foo${bar}baz"
Es expandido por el compilador a:
new scala.StringContext("foo", "baz").my(bar)
scala.StringContext
no tiene my
método, por lo tanto, se puede proporcionar por conversión implícita. Un interpolador personalizado con el mismo comportamiento que la orden interna s
interpolador entonces ser implementado de la siguiente manera:
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
}
}
Y la interpolación de my"foo${bar}baz"
se desugaría a:
new MyInterpolation(new StringContext("foo", "baz")).my(bar)
Tenga en cuenta que no hay restricción en los argumentos o el tipo de retorno de la función de interpolación. Esto nos lleva por un camino oscuro donde la sintaxis de interpolación se puede usar creativamente para construir objetos arbitrarios, como se ilustra en el siguiente ejemplo:
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
Interpoladores de cadenas como extractores.
También es posible utilizar la función de interpolación de cadenas de Scala para crear extractores elaborados (emparejadores de patrones), como quizás el más famoso empleado en la API de cuasiquotes de las macros de Scala.
Dado que n"p0${i0}p1"
desaparece del new StringContext("p0", "p1").n(i0)
, quizás no sea sorprendente que la funcionalidad del extractor esté habilitada al proporcionar una conversión implícita de StringContext
a una clase con propiedad n
de un tipo que define un método unapply
o unapplySeq
.
Como ejemplo, considere el siguiente extractor que extrae segmentos de ruta al construir una expresión regular a partir de las partes StringContext
. Luego podemos delegar la mayor parte del trabajo pesado al método unapplySeq
proporcionado por el resultado 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 _ => ???
}
Tenga en cuenta que el objeto de path
también podría definir un método de apply
para comportarse como un interpolador regular también.
Interpolación de cuerdas sin procesar
Puede utilizar el interpolador en bruto si desea que una cadena se imprima tal como está y sin ningún escape de literales.
println(raw"Hello World In English And French\nEnglish:\tHello World\nFrench:\t\tBonjour Le Monde")
Con el uso del interpolador en bruto , debería ver lo siguiente impreso en la consola:
Hello World In English And French\nEnglish:\tHello World\nFrench:\t\tBonjour Le Monde
Sin el interpolador en bruto , \n
\t
se habrían escapado.
println("Hello World In English And French\nEnglish:\tHello World\nFrench:\t\tBonjour Le Monde")
Huellas dactilares:
Hello World In English And French
English: Hello World
French: Bonjour Le Monde