创建控件构造,对Scala DSL中的换行符没有有趣的限制

时间:2014-06-04 20:52:07

标签: scala

我正在通过合同编写一个简单的DSL设计。以下是我想写的内容:

def incrX( i : Int ) {
      val x0 = x 
      pre( i >= 0 )
      post( x == x0+i )
      in {
          x += i 
      } }

到目前为止,我所做的是使pre成为一个采用布尔值并返回一个对象的特征方法。该对象有一个方法post,它接受​​一个布尔值并返回另一个对象。该对象有一个方法in,它接受​​一个Unit并返回()。通过该方案,我可以写

def incrX( i : Int ) {
      val x0 = x 
      pre( i >= 0 ) post( x == x0+i ) in { x += i } }

def incrX( i : Int ) {
      val x0 = x 
      pre( i >= 0
      ) post( x == x0+i
      ) in {
          x += i 
      } }

甚至

def incrX( i : Int ) {
      val x0 = x 
      (pre( i >= 0 )
       post( x == x0+i )
       in {
          x += i 
      } ) }

这很好,但不是我想要的。

有没有办法达到我想要的效果?

1 个答案:

答案 0 :(得分:2)

就好看的代码而言,我喜欢" dot alignment"的概念,这在Scala中非常常见,可以解决你的语法问题。

所以给出如下内容:

object Contract {
  def pre(c: => Boolean) = new ContractWithPre(c)
}
class ContractWithPre(preCond: => Boolean) {
  def post(c: => Boolean) = new ContractWithPreAndPost(preCond, c)
}
class ContractWithPreAndPost(preCond: => Boolean, postCond: => Boolean) {
  def in(body: => Unit) {
    require(preCond)
    body
    ensuring(postCond)
  }
}

你可以写:

Contract
  .pre(i >= 0)
  .post(x == x0+i)
  .in {
    x += i 
  }