这个问题的动机是试图找到this question的解决方案。
假设您希望使用以下语法构建层次结构:
root {
subA {
subB("b1.1")
subB("b1.2")
}
}
构造DSL应该是类型安全的,也就是说,不应该将subB
直接嵌套在root
中,或者将subA
嵌套在另一个subA
中root
}}。因此,我的想法是让方法subA
返回定义方法subB
的对象,后者又返回定义root
的对象。
我现在想要的是将代码块传递给 subA {
subB("b1.1")
subB("b1.2")
}
,即
subB
执行以使root
的调用绑定到root { r: Root =>
r.subA { sa: SubA =>
sa.subB("b1.1")
sa.subB("b1.2")
}
}
创建的对象。基本上就像这样
r
但无需明确接收sa
和this
。
问题:重新绑定接收器,特别是隐式Dynamic
- 接收器,在Scala中可能的代码块内 - 可能使用宏吗?
This article描述了一个用于XML树的类似结构的DSL。它们的实现基于xml html {
xml head {
xml title "Search Links"
}
}
功能,生成的DSL语法如下所示:
xml
然而,这种方法需要明确的接收器(这里是对象html
),更严重的是,我不认为它是类型安全的,因为它会静态地阻止你嵌套title
节点内的{{1}}节点。
答案 0 :(得分:0)
我不确定这是否可用,但它看起来与您编写的代码非常相似。我添加了,
并将{
和}
更改为(
和)
。
trait RootElement
trait SubAElement
def root(f:(() => RootElement)*) = ???
def subA(f:(() => SubAElement)*):() => RootElement = ???
def subB(s:String):() => SubAElement = ???
root(
subA (
subB("b1.1"),
subB("b1.2")
)
)
我不确定您是如何使用它的,如果您可以使用它,我可以根据用例尝试制作更具体的版本。
重新绑定接收器,特别是隐式的接收器,在Scala中可能的代码块内 - 可能使用宏吗?
不,据我所知,这不可能是开箱即用的。你可能会用宏来做到这一点,但我无法帮助你。我对宏观的了解有限,这告诉我这将是一次冒险。
为了在没有宏的情况下实现相同的效果,我创建了一个小例子。我已经删除了懒惰以使其更简洁。
class Root {
def subA(subA: SubA) = {
// do something with subA
}
}
class SubA {
def subB(s: String) = {
// do something with subB
}
}
case class RootElement(value: SubA)
case class SubAElement(value: String)
def root(rootElems: (RootElement)*): Root = {
val r = new Root
rootElems foreach { sub =>
r.subA(sub.value)
}
r
}
def subA(subElems: SubAElement*): RootElement = {
val sA = new SubA
subElems foreach { sub =>
sA.subB(sub.value)
}
RootElement(sA)
}
def subB(s: String): SubAElement = SubAElement(s)
root(
subA(
subB("b1.1"),
subB("b1.2")
)
)