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

欢迎!请参阅 关于 页面了解更多有关本网站如何运作的信息。

+2
错误
当 {{:pre}} 或 {{:post}} 条件列表中的谓词失败时,将显示与以下类似的消息


(defn must-be-a-map [m] {:pre [(map? m)]} m)
(must-be-a-map [])
;;=> AssertionErrorAssert failed: (map? m)  user/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 Assert failed: m must be a map due to some domain specific reason.
(map? m) user/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] http://wiki.science.ru.nl/tfpie/images/2/22/TFPIE2013_Steps_Towards_Teaching_Clojure.pdf

3 个回答

0
_由:coltnz_ 发表评论

所采用的方法与描述中提倡的方法不同,因为它不需要映射。现有的 spec

{: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) "没有字母"


                                            (hasNum arg) "没有数字"


                                            (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 报告)
...