46 votes

Interpolation de chaînes dans Scala 2.10 - Comment interpoler une variable de chaîne?

Chaîne d'interpolation est disponible en Scala de départ Scala 2.10

C'est l'exemple de base

 val name = "World"            //> name  : String = World
 val message = s"Hello $name"  //> message  : String = Hello World

Je me demandais si il existe un moyen de faire de l'interpolation dynamique, par exemple, la suite (ne compile pas, juste pour des fins d'illustration)

 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)
  1. Est-il un moyen de "dynamique" évaluer une Chaîne comme ça? (ou est-il foncièrement mauvais / pas possible)

  2. Et qu'est - s exactement? ce n'est pas une méthode def (apparemment, c'est une méthode de StringContext), et non pas un objet (s'il l'était, il aurait jeté une autre erreur de compilation que pas trouvé , je pense)


Edit:

Basé sur la accepté de répondre, voici la solution pour l'exemple ci-dessus à l'aide de Rex suggestion

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

36voto

Rex Kerr Points 94401

s est une méthode d' StringContext (ou quelque chose qui peut être converti implicitement StringContext). Lorsque vous écrivez

whatever"Here is text $identifier and more text"

le compilateur desugars en

StringContext("Here is text ", " and more text").whatever(identifier)

Par défaut, StringContext vous donne s, f, et raw* méthodes.

Comme vous pouvez le voir, le compilateur lui-même reprend le nom et la donne à la méthode. Depuis ce qui se passe au moment de la compilation, vous ne pouvez pas raisonnablement le faire dynamiquement--le compilateur ne dispose pas d'informations sur les noms de variables lors de l'exécution.

Vous pouvez utiliser vars, cependant, de sorte que vous pouvez échanger dans les valeurs que vous souhaitez. Et la valeur par défaut s méthode appelle juste toString (comme vous le souhaitez), donc vous pouvez jouer à des jeux comme

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 a déjà été appelée par le REPL dans cet exemple).

C'est le mieux que vous pouvez faire.

*raw est cassé et n'est pas prévu pour être fixé jusqu'à ce 2.10.1; seul le texte avant qu'une variable est réellement cru (pas de traitement d'échappement). Afin de tenir à distance sur l'utilisation que l'on jusqu'à ce que 2.10.1 est sorti, ou de regarder le code source et de définir votre propre. Par défaut, il n'y a pas de traitement d'échappement, afin de définir votre propre est assez facile.

12voto

Eran Medan Points 12234

Voici une solution possible au n ° 1 dans le contexte de la question initiale basée sur l'excellente réponse 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
 

7voto

Kipton Barros Points 12445
  1. Chaîne d'interpolation qui se passe au moment de la compilation, le compilateur n'ont généralement pas de suffisamment d'informations pour interpoler s(str). Il attend une chaîne littérale, selon le protocole SIP.
  2. En vertu de l'Utilisation Avancée dans la documentation que vous avez lié, il est expliqué qu'une expression de la forme id"Hello $name ." est traduit au moment de la compilation d' new StringContext("Hello", "."). id(name).

Notez que id peut être défini par l'utilisateur de l'interpolateur introduite par un implicite de la classe. La documentation donne un exemple pour un json de l'interpolateur,

implicit class JsonHelper(val sc: StringContext) extends AnyVal {
  def json(args: Any*): JSONObject = {
    ...
  }
}

1voto

jsalvata Points 1015

Ceci est par nature impossible dans l’implémentation actuelle: les noms de variables locales ne sont pas disponibles au moment de l’exécution - peuvent être conservés en tant que symboles de débogage, mais peuvent également avoir été supprimés. (Les noms des variables membres sont, mais ce n'est pas ce que vous décrivez ici).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X