我可能会遗漏Scala字符串插值机制的基本内容。我想做什么:
// this could come from a config file, string here to demo
val brown = "BROWN"
val cow = "Moo"
val replaceInMe = "How Now ${brown} ${cow}"
//this does what I eventually want:
val output = s"How Now ${brown} ${cow}"
//But, since the variables 'brown' and 'cow' are defined,
//I really wold like to be able to do something like:
val output = s(replaceInMe)
这甚至可能吗?
编辑:根据下面的第一个答案,必须将变量replaceInMe
作为输入。在这里我将它定义为一个String,但它实际上是一个从配置文件读取的行。
答案 0 :(得分:5)
没有。 documentation清楚地表明您只能使用字符串文字,而不能使用任何字符串对象。
这是因为当编译器看到:
s"How Now ${brown} ${cow}"
它将其转换为:
new StringContext("How Now ", " ", "").s(brown, cow)
编译器不能使用任意标识符执行此操作,因为这些值很可能在运行时设置,而不是在编译时设置。想象一下,replaceInMe
是从外部文件中提取的值。外部文件中的字符串如何可能知道程序中的运行时变量?如果它们没有被定义怎么办?使用字符串插值,这是通过编译错误处理的,这显然不会在运行时发生。在运行时,您需要另一种方法来处理缺失值。
最好使用某种配置库来处理这个问题。
答案 1 :(得分:2)
但等等,还有更多!它是一个编译器和一个模板引擎!
scala> import javax.script._
import javax.script._
scala> val se = new ScriptEngineManager().getEngineByName("scala")
se: javax.script.ScriptEngine = scala.tools.nsc.interpreter.Scripted@2a742aa2
scala> val animal = new { override def toString = "cow" } // some value
animal: AnyRef = cow
scala> se.put("animal", animal)
scala> val template = "I see a $animal"
template: String = I see a $animal
scala> se.eval(s"""s"$template, she said."""")
res1: Object = I see a cow, she said.
,或者
scala> val sc = se.asInstanceOf[ScriptEngine with Compilable]
sc: javax.script.ScriptEngine with javax.script.Compilable = scala.tools.nsc.interpreter.Scripted@2a742aa2
scala> val cs = sc.compile(s"""s"$template, she said."""")
cs: javax.script.CompiledScript = scala.tools.nsc.interpreter.Scripted$WrappedRequest@1dba7721
scala> cs.eval()
res4: Object = I see a cow, she said.
scala> val ctx = sc.createBindings()
ctx: javax.script.Bindings = javax.script.SimpleBindings@1ad28f2
scala> ctx.put("animal", "frog")
res5: Object = null
scala> cs.eval(ctx)
res6: Object = I see a frog, she said.
只是为了表明“编译时间”是相对的:
scala> val cs = sc.compile("""s"There's no such $thing in scope."""")
<console>:12: error: not found: value thing
s"There's no such $thing in scope."
^
javax.script.ScriptException: compile-time error
at scala.tools.nsc.interpreter.Scripted.scala$tools$nsc$interpreter$Scripted$$$anonfun$7(Scripted.scala:113)
at scala.tools.nsc.interpreter.Scripted$DynamicContext.apply(Scripted.scala:38)
at scala.tools.nsc.interpreter.Scripted.compile(Scripted.scala:101)
at scala.tools.nsc.interpreter.Scripted.compile(Scripted.scala:124)
... 30 elided
答案 2 :(得分:0)
是的,这是可能的。 只需在replaceInMe之前定义val&#39的棕色和牛,就像:
在您的情况下,它不起作用,因为您无法在评估后更改replaceInMe。它是一种价值类型。
val brown = "BROWN"
val cow = "Moo"
// this could come from a config file, string here to demo
val replaceInMe = s"How Now ${brown} ${cow}"
println( replaceInMe )
了解更多详情: http://docs.scala-lang.org/overviews/core/string-interpolation.html