我的问题可能是人为的,我想将其视为可行性证明,而不是推荐的东西。 为了给你一些上下文,我会尝试在嵌入式DSL中使用与
不同的语法val myVal = "someContent"
我希望能够做到这样的事情:
assign("SomeContent","someVariable") => converted to
someVariable = "SomeContent"
然后在代码中,变量可用。 通常我们可以在REPL中使用类似的东西:
assign("John","name")
println("Hello " + name)
我一直在考虑使用宏(或ScalaCompiler插件,但我认为这里更复杂)才能做到这一点。 首先,我不知道这对宏来说是否可行。
考虑到我只会操作String而我开始使用类似
的东西,我已经开始了一些简单化的东西def assign(content: String, targetVal: String):Unit = macro assignMacro
def assignMacro(c:Context)(content: c.Expr[String],
targetVal: c.Expr[String]):c.expr[Unit] = {
import c.universe._
c.Expr[Unit](ValDef(Modifiers(), TermName(targetVal.value),
TypeTree(), Literal(Constant(content.value)))
}
不幸的是,它似乎因为几个错误而失败
我有点卡住了。 首先这可能吗?我猜是的;) 我怎么能实现这个目标呢?
感谢您的帮助
最好的问候
答案 0 :(得分:3)
2.10和2.11中的def宏都扩展为块,这意味着它们引入的定义变为该块的本地定义。这可能会在宏观天堂发生变化,但我不确定何时以及如何。
目前,Scala中的宏没有提供将新变量透明地引入现有范围的方法。这是Scala宏的演化历史工件,这是由于我们的反射组优先考虑黑盒宏(宏的行为类似于常规方法,完全由其类型签名描述,因此人类和程序可以将其实现视为黑盒而不会丢失)任何事情)。
最近对whitebox宏的兴趣(不适合黑盒方案的宏)产生了一些结果,但这些结果尚未包含在主线Scala中。我将在明天的Strange Loop演讲中详细阐述这个问题:https://thestrangeloop.com/sessions/evolution-of-scala-macros。
与此同时,您可以查看可能提供您正在寻找的自由度的宏注释。例如,通过适当地定义mydsl
注释,您可以拥有
@mydsl
def foo = {
assign("SomeContent", "someVariable")
...
}
转变为
def foo = {
someVariable = "SomeContent"
...
}