我正在通过合同编写一个简单的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
} ) }
这很好,但不是我想要的。
有没有办法达到我想要的效果?
答案 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
}