Eli*_*der 7 scheme design-by-contract eiffel racket
我知道Eiffel(祖先)和Racket都实现了"按合同设计"的功能.可悲的是,我不确定如何区别于另一个.Eiffel的DBC依赖于OOP范式和继承,但是Racket,一种非常不同的语言如何解释这种差异?
小智 13
球拍的主要声称是合同声名鹊起,并且处理ho功能是日常球拍编程的重要组成部分.
您可能还想查看本文的前两部分:
http://www.ccs.neu.edu/scheme/pubs/oopsla01-ff.pdf
首先,此时您最好的信息来源是" 球拍指南",该指南旨在作为介绍性文本而非参考手册.具体来说,有一个关于合同的广泛章节将有所帮助.编辑:另见罗比指出的论文,他是主要的球拍合约人.
至于你的问题 - 我对埃菲尔合同系统了解不多,但我认为它先于Racket的系统.然而(这又是一个"IIRC")我认为Racket的合同系统是第一个引入更高订单合同的系统.具体来说,当您处理更高阶函数时,分配适当的责任会变得更复杂一些 - 例如,如果您使用foo具有契约的函数X? -> Y?并且您发送的值与不匹配的值那么发送此函数X?的客户端代码值得foo责备.但是如果你的函数是(X? -> Y?) -> Z?并且X?谓词不满足,那么责任归于foo自身,而不是客户端(如果Y?不满意那么责任仍在客户端).
我想你在问,如果没有OOP和继承,合同系统怎么能运作?作为不熟悉Eiffel的Racket的用户,我想知道为什么合同系统与OOP和继承有关.:)
在实际层面上,我认为Racket契约是一种获得静态类型声明的一些好处的方法,同时保持动态类型语言的灵活性.加上合同不仅仅是类型,还可以填补断言的作用.
例如,我可以说一个函数需要一个完全整数的参数......但也要说它应该是一个精确的正整数,或某些特定值的并集,或者实际上是对传递值的任意复杂测试.通过这种方式,Racket中的契约将你可能做的事情与(a)类型声明和(b)C/C++中的断言结合起来.
在Racket中签订合同的一个问题是它们可能很慢.解决这个问题的一种方法是在开发时首先使用它们,然后选择性地从"内循环"类型的函数中去除它们.我尝试过的另一种方法是批量打开/关闭它们:制作一对模块,例如contract-on.rkt和contract-off.rkt,后者提供了一些无用的宏.让您的模块需要contract.rkt,它提供-on或-off文件中的所有文件.这就像在DEBUG vs RELEASE模式下编译一样.
如果你是来自埃菲尔,也许我的C/C++对Racket合约的倾向没有帮助,但无论如何我想分享它.