在Scala DSL中创建对换行符没有有趣限制的控件构造
我正在为契约式设计编写一个简单的DSL。以下是我希望能够写的:在Scala DSL中创建对换行符没有有趣限制的控件构造,scala,Scala,我正在为契约式设计编写一个简单的DSL。以下是我希望能够写的: def incrX( i : Int ) { val x0 = x pre( i >= 0 ) post( x == x0+i ) in { x += i } } 到目前为止,我所做的是使pre成为一个trait方法,它接受一个布尔值并返回一个对象。该对象有一个方法post,该方法接受布尔值并返回另一个对象。该对象在中有一个方法,该方法获取一
def incrX( i : Int ) {
val x0 = x
pre( i >= 0 )
post( x == x0+i )
in {
x += i
} }
到目前为止,我所做的是使pre
成为一个trait方法,它接受一个布尔值并返回一个对象。该对象有一个方法post
,该方法接受布尔值并返回另一个对象。该对象在中有一个方法,该方法获取一个单位并返回()。有了这个计划,我就可以写作了
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
} ) }
很好,但不是我想要的
有什么方法可以实现我想要的吗?就好看的代码而言,我喜欢“点对齐”的概念,它在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
}
例如,在pre
和post
部分之间使用&
或带是可以接受的吗?Scala有一个内置的API,您可以使用它,比如:def incrX(i:Int)={val x0=x;require(i>=0);(x+=i)确保(x==x0+i);}
@GáborBakos i可能,“如果没有其他选择的话,”wingedsubmariner说,那是真的。我喜欢这个答案,但它不能肯定地回答我的“这能做到吗”的问题。相反,它很好地回答了一个显而易见的后续问题:“如果它不能像我所希望的那样完成,还有什么其他方法可以创建类似的语法。”@Theodore Norvell:如果你问“这可以在不修改代码的情况下完成吗”(比如:通过一些外部修改来改变解析器的行为),那么我的答案是:不,我目前没有看到任何可能性,除了修改解析器。也就是说,我仍然认为你想要的是可能的,仅仅通过一个非常小的语法修改:)。
Contract
.pre(i >= 0)
.post(x == x0+i)
.in {
x += i
}