Checking Clojure pre-conditions without running the function?

大憨熊 提交于 2019-12-24 10:41:41

问题


I have one function that does some (possibly lengthy) work (defn workwork [x] ...) and some other functions to check if the call will succeed ahead of time (defn workwork-precondition-1 [x] ...).

The precondition functions should be evaluated every time workwork is called (e.g. using :pre). The precondition functions should also be collected (and:ed) in a single function and made available to client code directly (e.g. to disable a button).

Which is the idiomatic way to solve this in Clojure while avoiding code duplication?

In particular, is there any way to evaluate the pre-conditions of a function without running the function body?


回答1:


You can just collect your preconditions into a function:

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

Then call the function in a :pre-style precondition:

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

For functions introduced using defn, you can extract the :pre-style preconditions from the metadata on the Var:

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

And similarly for the :arglists entries for any other arities.

There are two caveats here:

  1. The automatically-generated :arglists entry in the Var's metadata maybe be overridden. Overriding :arglists results in the above kind of useful automatically-generated metadata to be thrown out.

  2. The {:pre [(foo-pre x)]} value returned by the above (-> #'foo meta …) expression contains foo-pre as a literal symbol – it'd be your responsibility to figure out which function it referred to at foo's point of definition. (This may or may not be possible – for example foo could be defn'd inside a top-level let or letfn form, with foo-pre a local function.)

And finally, anonymous functions may use :pre and :post, but there is currently no mechanism for extracting them from the function itself.




回答2:


to evaluate the function precondition without running the function body,you can use robert-hooke library 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)



来源:https://stackoverflow.com/questions/29320127/checking-clojure-pre-conditions-without-running-the-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!