2024 年 Clojure 状态调查! 中分享您的想法。

欢迎!请参见 关于 页面以获取更多有关此如何工作的信息。

+2
错误
当前在 {{:pre}} 或 {{:post}} 条件列表中的谓词失败会导致类似以下的消息显示


(defn must-be-a-map [m] {:pre [(map? m)]} m)
(must-be-a-map [])
;;=> AssertionError 断言失败:1 (map? m)  用户/must-be-a-map (form-init.....clj:1)


通过允许将特定消息字符串与 {{:pre}} 和 {{:post}} 条件中的每个谓词相关联,可以显著增加异常消息的描述性。

谓词函数及其相关消息字符串可以用一个映射中的值对来指定


(defn must-be-a-map
  [m]
  {:pre [{(map? m) "m must be a map due to some domain specific reason."}]}
  m)


然后这将产生以下错误消息

(must-be-a-map 10)
AssertionError 断言失败:m must be a map due to some domain specific reason.
(map? m) 用户/must-be-a-map (form-init.....clj:1)


这将允许指定不带消息的谓词,同时指定与其相关联的谓词消息对,如下所示


(defn n-and-m [n m] {:pre [(number? n) {(map? m) "You must provide a map!"}]})


此更改不会破坏任何现有功能,并仍然允许在代码中的其他地方预定义谓词。

因此,预置和后置条件可以提供进一步记录函数内外部的方法,简化在开发库时提供有意义输出的过程,也许使语言更适合教学环境[1]

[1] http://wiki.science.ru.nl/tfpie/images/2/22/TFPIE2013_Steps_Towards_Teaching_Clojure.pdf

3 答案

0
评论来自:coltnz_

所附方法与描述中提倡的方法不同,因为它不需要地图。现有的规范为:

{:pre [pre-expr*]}
 :post [post-expr*]}

实际上变成了:

{:pre [(pre-expr assert-msg?)*]}
 :post [(pre-expr assert-msg?)*]}


其中 assert-msg 是一个字符串。注意这意味着一个表达式后面的第二个字符串(可能是错误的)将被视为一个真的 pre-expr。

人为示例:

(defn print-if-alphas-and-nums [arg] {:pre [(hasAlpha arg) "Not alphabetic"
                                            (hasNum arg) "Not numeric"
                                            (canPrint arg)]}
  (println arg))

user=> (print-if-alphas-and-nums "a5%")
a5%
nil
user=> (print-if-alphas-and-nums "$$%")
AssertionError:断言失败:没有字母
(hasAlpha arg)  user/print-if-alphas-and-nums (NO_SOURCE_FILE:19)


我已经考虑将规范进一步扩展到(pre-expr assert-msg? data-map}*),也许可以得到 assert-info、assert-data 中的 ex-info、ex-data 的支持来传达诊断信息(局部变量?)。地图可以包含一个:msg 键,或者地图可能是消息字符串的附加。不过在这个点上,我想先等一下。

我还考虑在消息中允许使用 % 替换函数返回值,就像 :post conds 一样,但如何转义?

 

0
by

评论来自:coltnz

我应该指出,测试还包括目前尚未覆盖的现有功能。

0
by
参考:https://clojure.atlassian.net/browse/CLJ-1817(由 alex+import 报告)
...