1

我有一个功能可以完成一些(可能很长)工作(defn workwork [x] ...),还有一些其他功能可以检查调用是否会提前成功(defn workwork-precondition-1 [x] ...)

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

在避免代码重复的同时,在 Clojure 中解决这个问题的惯用方法是什么?

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

4

2 回答 2

4

您可以将您的先决条件收集到一个函数中:

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

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

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

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

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

:arglists对于任何其他 arities的条目也是如此。

这里有两个警告:

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

  2. {:pre [(foo-pre x)]}上述表达式返回的值包含(-> #'foo meta …)一个foo-pre文字符号——你有责任找出它在foo定义点引用的函数。(这可能会也可能不会——例如foo可以defn在顶层letletfn表单中使用foo-pre本地函数。)

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

于 2015-03-28T20:28:56.333 回答
0

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


    (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)

于 2015-03-29T06:19:46.223 回答