import com.twitter.util.Eval object InterpolationDemo { case class Indicator(basetime: String, key: String, value: Double) case class ExprImplicit(basetime: String, data: Map[String, Double]) implicit class IndicatorExpressionHelper(val sc: StringContext) extends AnyVal { def indicator(args: Any*)(implicit default: ExprImplicit): Indicator = { val strings = sc.parts.iterator val expressions = args.iterator var basetime: Option[String] = None var key: String = null var value: Double = -1 val env = default.data.map{ case (k, v) => s"val $k = $v" }.mkString("\n") while (strings.hasNext && expressions.hasNext) { val k = strings.next.trim.stripPrefix(",").stripSuffix(":").trim val v = expressions.next k match { case "basetime" => basetime = Some(v.toString) case "key" => key = v.toString case "value" => val eval = new Eval val expr = s"""$env |${v.toString} |""".stripMargin try { value = eval[Double](expr) } catch { case e: com.twitter.util.Eval.CompilerException => println(s"key[$key] expr[${expr.split("\n").mkString("; ")}] exception[${e.getMessage}]") } case _ => println(v) } } if (strings.nonEmpty && strings.next.nonEmpty) { println("error: " + strings.next) } if (expressions.nonEmpty) { println("error: " + expressions.next) } if (basetime.isDefined) { Indicator(basetime.get, key, value) } else { Indicator(default.basetime, key, value) } } } def main(args: Array[String]): Unit = { val basetime = "2019042805" implicit val expr = ExprImplicit(basetime, Map("a" -> 50, "b" -> 2300, "c" -> 230)) println((indicator"basetime: $basetime, key: ${"ratio_1"} , value: ${"a/b"}")) println((indicator"basetime: ${"2019043009"}, key: ${"ratio_2"} , value: ${"c/b"}")) println((indicator"key: ${"ratio_1"} , value: ${"a/b"}")) println((indicator"key: ${"ratio_1"} , value: ${"d/b"}")) } }