在没有 运行 函数的情况下检查 Clojure 前置条件?
Checking Clojure pre-conditions without running the function?
我有一个函数可以完成一些(可能很长的)工作 (defn workwork [x] ...)
和一些其他函数可以提前检查调用是否成功 (defn workwork-precondition-1 [x] ...)
。
每次调用 workwork
(例如使用 :pre
)时,都应评估前置条件函数。前置条件函数也应该收集(和:ed)在一个函数中,并直接提供给客户端代码(例如禁用按钮)。
在 Clojure 中解决这个问题同时避免代码重复的惯用方法是什么?
特别是,有没有什么方法可以在没有 运行 函数体的情况下评估函数的前置条件?
您可以将前提条件收集到一个函数中:
(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)]}
对于任何其他参数的 :arglists
条目也是如此。
这里有两个注意事项:
Var 元数据中自动生成的 :arglists
条目可能被覆盖。覆盖 :arglists
会导致上述有用的自动生成的元数据被丢弃。
上述(-> #'foo meta …)
表达式返回的{:pre [(foo-pre x)]}
值包含foo-pre
作为文字符号 – 它'你有责任弄清楚它在 foo
的定义点指的是哪个函数。 (这可能会也可能不会——例如 foo
可以在顶级 let
或 letfn
形式中 defn
,其中 foo-pre
局部函数。)
最后,匿名函数可能会使用 :pre
和 :post
,但目前还没有从函数本身中提取它们的机制。
要在没有 运行 函数体的情况下计算函数前提条件,您可以使用 robert-hooke
库 https://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)
我有一个函数可以完成一些(可能很长的)工作 (defn workwork [x] ...)
和一些其他函数可以提前检查调用是否成功 (defn workwork-precondition-1 [x] ...)
。
每次调用 workwork
(例如使用 :pre
)时,都应评估前置条件函数。前置条件函数也应该收集(和:ed)在一个函数中,并直接提供给客户端代码(例如禁用按钮)。
在 Clojure 中解决这个问题同时避免代码重复的惯用方法是什么?
特别是,有没有什么方法可以在没有 运行 函数体的情况下评估函数的前置条件?
您可以将前提条件收集到一个函数中:
(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)]}
对于任何其他参数的 :arglists
条目也是如此。
这里有两个注意事项:
Var 元数据中自动生成的
:arglists
条目可能被覆盖。覆盖:arglists
会导致上述有用的自动生成的元数据被丢弃。上述
(-> #'foo meta …)
表达式返回的{:pre [(foo-pre x)]}
值包含foo-pre
作为文字符号 – 它'你有责任弄清楚它在foo
的定义点指的是哪个函数。 (这可能会也可能不会——例如foo
可以在顶级let
或letfn
形式中defn
,其中foo-pre
局部函数。)
最后,匿名函数可能会使用 :pre
和 :post
,但目前还没有从函数本身中提取它们的机制。
要在没有 运行 函数体的情况下计算函数前提条件,您可以使用 robert-hooke
库 https://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)