我更喜欢 Lisp 变体中的示例(Clojure 或 Scheme 的加分项),因为这是我最熟悉的,但任何关于函数式语言中 DBC 的反馈当然对更大的社区都很有价值。
这是一个明显的方法:
(defn foo [action options]
(when-not (#{"go-forward" "go-backward" "turn-right" "turn-left"} action)
(throw (IllegalArgumentException.
"unknown action")))
(when-not (and (:speed options) (> (:speed options) 0))
(throw (IllegalArgumentException.
"invalid speed")))
; finally we get to the meat of the logic)
我不喜欢这个实现的是合约逻辑模糊了核心功能;该函数的真正目的在条件检查中丢失了。这与我在这个问题中提出的问题相同。在像 Java 这样的命令式语言中,我可以使用文档中嵌入的注释或元数据/属性将合同从方法实现中移出。
有没有人研究过在 Clojure 中向元数据添加合同?如何使用高阶函数?还有哪些其他选择?