Interpolación de cadenas en Scala 2.10-¿Cómo interpolar una variable de cadena?
La interpolación de cadenas está disponible en Scala a partir de Scala 2.10
Este es el ejemplo básico
val name = "World" //> name : String = World
val message = s"Hello $name" //> message : String = Hello World
Me preguntaba si hay una manera de hacer interpolación dinámica, por ejemplo, lo siguiente (no compila, solo con fines ilustrativos)
val name = "World" //> name : String = World
val template = "Hello $name" //> template : String = Hello $name
//just for illustration:
val message = s(template) //> doesn't compile (not found: value s)
-
¿Hay una manera de evaluar" dinámicamente " una cadena como esa? (o es inherentemente incorrecto / no es posible)
-
¿Y qué es
s
exactamente?no es un método def(aparentemente es un método enStringContext
), y no un objeto (si lo fuera, habría arrojado un error de compilación diferente que no encontrado Creo)
4 answers
s
es en realidad un método en StringContext
(o algo que se puede convertir implícitamente de StringContext
). Cuando escribes
whatever"Here is text $identifier and more text"
El compilador lo desugar en
StringContext("Here is text ", " and more text").whatever(identifier)
Por defecto, StringContext
te da s
, f
, y raw
* métodos.
Como puede ver, el propio compilador elige el nombre y se lo da al método. Dado que esto sucede en tiempo de compilación, no puede hacerlo de manera sensible y dinámica the el compilador no tiene información sobre los nombres de variables en ejecución.
Puede usar vars, sin embargo, para que pueda intercambiar los valores que desee. Y el método predeterminado s
solo llama a toString
(como era de esperar) para que pueda jugar juegos como
class PrintCounter {
var i = 0
override def toString = { val ans = i.toString; i += 1; ans }
}
val pc = new PrintCounter
def pr[A](a: A) { println(s"$pc: $a") }
scala> List("salmon","herring").foreach(pr)
1: salmon
2: herring
(0 ya fue llamado por el REPL en este ejemplo).
Eso es lo mejor que puedes hacer.
*raw
está roto y no está programado para ser arreglado hasta 2.10.1; solo el texto antes de una variable es realmente raw (sin procesamiento de escape). Así que espere en el uso de que uno hasta 2.10.1 es fuera, o mirar el código fuente y definir su propio. De forma predeterminada, no hay procesamiento de escape, por lo que definir el suyo es bastante fácil.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-07 09:31:44
Aquí hay una posible solución a #1 en el contexto de la pregunta original basada en la excelente respuesta de Rex
val name = "World" //> name: String = World
val template = name=>s"Hello $name" //> template: Seq[Any]=>String = <function1>
val message = template(name) //> message: String = Hello World
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-07 01:29:18
- La interpolación de cadenas ocurre en tiempo de compilación, por lo que el compilador generalmente no tiene suficiente información para interpolar
s(str)
. Se espera un literal de cadena, de acuerdo con el SIP. - Bajo Advanced Usage en la documentación que enlazó, se explica que una expresión de la forma
id"Hello $name ."
se traduce en tiempo de compilación anew StringContext("Hello", "."). id(name)
.
Tenga en cuenta que id
puede ser un interpolador definido por el usuario introducido a través de una clase implícita. Documentación da un ejemplo para un interpolador json
,
implicit class JsonHelper(val sc: StringContext) extends AnyVal {
def json(args: Any*): JSONObject = {
...
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-07 00:00:22
Esto es inherentemente imposible en la implementación actual: los nombres de variables locales no están disponibles en el momento de la ejecución may pueden mantenerse como símbolos de depuración, pero también pueden haber sido eliminados. (Los nombres de las variables de los miembros lo son, pero eso no es lo que estás describiendo aquí).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-07 00:17:25