7

I know that both Eiffel (the progenitor) and Racket both to implement "Design by Contract" features. Sadly, I am not sure how one would different from the other. Eiffel's DBC is reliant on the OOP paradigm and inheritance, but how would Racket, a very different language account for such a disparity?

4

3 回答 3

13

Racket 声名鹊起的主要主张是责备的概念,而处理 ho 函数无疑是日常 Racket 编程的重要组成部分。

您可能还想查看本文的前两节:

http://www.ccs.neu.edu/scheme/pubs/oopsla01-ff.pdf

于 2011-04-15T02:41:52.837 回答
9

首先,此时您最好的信息来源是球拍指南,它旨在作为介绍性文本而不是参考手册。具体来说,有一个关于合同的详尽章节会有所帮助。编辑:另请参阅罗比指出的文件,他是主要的球拍合同人。

至于你的问题——我对 Eiffel 合同系统了解不多,但我认为它先于 Racket 的系统。但是(这又是一个“IIRC”)我认为 Racket 的合约系统是第一个引入更高阶合约的系统。具体来说,当你处理高阶函数时,分配适当的责备会变得更复杂一些——例如,如果你使用一个foo具有合约的函数X? -> Y?并且你向它发送一个不匹配的值,X?那么发送这个的客户端代码价值foo归咎于。但是如果你的函数是(X? -> Y?) -> Z?并且X?谓词不满足,那么责任就归咎于foo它自己,而不是客户(如果Y?不满足,那么责任仍然在客户身上)。

于 2011-04-15T02:16:54.730 回答
8

我想你在问,没有 OOP 和继承的合同系统怎么可能工作?作为一个不熟悉 Eiffel 的 Racket 用户,我想知道为什么合同系统会与 OOP 和继承有关。:)

在实践层面上,我认为 Racket 契约是一种获得静态类型声明的一些好处的方式,同时保持动态类型语言的灵活性。Plus 合同不仅仅是类型,还可以充当断言的角色。

例如,我可以说一个函数需要一个精确整数的参数......但也可以说它应该是一个精确的整数,或者某些特定值的联合,或者实际上是对传递值的任意复杂测试。通过这种方式,Racket 中的合约结合了您可能对 (a) 类型声明和 (b) C/C++ 中的断言所做的事情。

Racket 中合同的一个问题是它们可能很慢。解决这个问题的一种方法是在开发时首先使用它们,然后有选择地删除它们,尤其是从“内循环”类型的函数中。我尝试过的另一种方法是批量打开/关闭它们:制作一对模块,如contracts-on.rkt 和contract-off.rkt,后者提供一些无操作宏。让您的模块需要一个contracts.rkt,它提供了-on 或-off 文件中的所有内容。这就像在 DEBUG 与 RELEASE 模式下编译。

如果你来自埃菲尔,也许我对 Racket 合同的 C/C++ 倾向不会有帮助,但我还是想分享它。

于 2011-04-15T17:34:32.213 回答