2

问题

这个问题的动机是试图为这个问题找到一个解决方案。

假设您想使用以下语法构建层次结构:

root {
  subA {
    subB("b1.1")
    subB("b1.2")
  }
}

构造 DSL 应该是类型安全的,也就是说,不能将 asubB直接嵌套在 中root,或者将 a 嵌套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")
  }
}

但不必使接收者rsa明确的。

问题:this在 Scala 中是否可以在代码块中重新绑定接收器,尤其是隐式接收器- 可能使用宏?

其他方法

本文描述了一个外观相似的 XML 树构造 DSL。它们的实现基于该Dynamic特性,生成的 DSL 语法如下所示:

xml html {
  xml head {
    xml title "Search Links"
  }
}

但是,这种方法需要显式的接收器(这里是 object xml),更严重的是,我认为它不是类型安全的,因为它会静态地阻止您将html节点嵌套在title节点中。

4

1 回答 1

0

我不确定这是否可用,但它看起来与您编写的代码非常相似。我已将 and 添加并,更改为{and 。}()

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")
  )
)

我不确定您想如何使用它,如果您提供的话,我可以尝试根据用例制作更具体的版本。


编辑

重新绑定接收器,尤其是隐式的 this-receiver,是否可以在 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")
  )
)
于 2013-02-16T13:30:30.517 回答