But wait, there's more! It's a compiler and a templating engine!
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.
or,
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.
Just to show that "compile time" is relative:
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