在不运行该功能的情况下检查Clojure前置条件?

时间:2015-03-28 17:15:50

标签: clojure idioms preconditions

我有一个函数执行一些(可能很长的)工作(defn workwork [x] ...)和其他一些函数来检查调用是否会提前成功(defn workwork-precondition-1 [x] ...)

每次调用workwork时都应评估前置条件函数(例如,使用:pre)。前置条件函数也应该在单个函数中收集(和编辑),并直接用于客户端代码(例如,禁用按钮)。

哪种方法可以在Clojure中解决这个问题,同时避免代码重复?

特别是,有没有办法在不运行函数体的情况下评估函数的前置条件?

2 个答案:

答案 0 :(得分:4)

您可以将前置条件收集到函数中:

(defn foo-pre [x]
  (even? x))

然后在:pre - 样式前置条件中调用该函数:

(defn foo [x]
  {:pre [(foo-pre x)]}
  …)

对于使用defn引入的函数,您可以从Var上的元数据中提取:pre式前提条件:

(-> #'foo meta :arglists first meta)
;= {:pre [(foo-pre x)]}

同样对于任何其他arities的:arglists条目。

这里有两点需要注意:

  1. 可能会覆盖Var的元数据中自动生成的:arglists条目。覆盖:arglists会导致抛出上述类型的有用自动生成的元数据。

  2. 上述{:pre [(foo-pre x)]}表达式返回的(-> #'foo meta …)值包含foo-pre作为文字符号 - 您有责任弄清楚它在foo的定义点引用了哪个函数。 (这可能是也可能是不可能的 - 例如foo可以defn位于顶级letletfn表单中,foo-pre本地功能。)

  3. 最后,匿名函数可以使用:pre:post,但目前没有从函数本身中提取它们的机制。

答案 1 :(得分:0)

在不运行函数体的情况下评估函数前置条件,可以使用robert-hookehttps://github.com/technomancy/robert-hooke/


    (use 'robert.hooke)

    (defn workwork [x] ...)

    (defn workwork-precondition-1 
      [f x]
      (if (precondition-1-satisfied? x)
        (f x)
        :precondition-1-not-satisfied))

    (add-hook #'workwork #'workwork-precondition-1)