Clojure:在解构时报告失败的值

时间:2016-01-22 16:59:57

标签: error-handling clojure preconditions

SO post之后,我想在我的函数中打印前置条件的值。然而,在下列情况下(可能是解构),我失败了:

我有一个dir?辅助函数(可以跳过这个):

(defn dir? [s]
  "returns true if the string passed is is an existing directory"
  (->> (clojure.java.io/file s)
       ((juxt #(.exists %) #(.isDirectory %)))
       (every? true?)))

它工作正常,使用is宏,我得到一些很好的错误消息,我可以看到测试和传递的参数:

(is (dir? (io/file "resources/static"))) ;; => true

(is (dir? (io/file "resources/statice"))) ;; typo, error below
  

在clojure.lang.PersistentList$EmptyList@1中失败   (boot.user4515592986834245937.clj:86)期待:(dir?(io / file   “resources / statice”))actual :(不是(dir?#object [java.io.File   0x6730a420“resources / statice”]))

然而,当试图在前置条件:pre中使用它时,我得到一个丑陋的错误:

(defn make-something
  [&{:keys [dir]
     :or {dir "default-dir"}}]
  {:pre [(is (dir? (clojure.java.io/file dir)))]}
  ;;... do something with these
 )

(make-something :dir "resources/statices") ;; doesn't exist
  

clojure.lang.Compiler $ CompilerException:java.lang.AssertionError:   断言失败:(是(dir?(io / file dir))),   编译:(boot.user4515592986834245937.clj:80:12)                  java.lang.AssertionError:断言失败:(是(dir?(io / file dir)))

如何在我的函数中获得一条很好的错误信息,就像上面那样?

如果重要,我正在使用Clojure 1.7。

1 个答案:

答案 0 :(得分:1)

您需要检查代码(dir?功能)。以下代码片段适用于我:

(require '[clojure.java.io :as io])

(defn dir? [s]
  (let [dir (io/file s)]
    (and (.exists dir)
         (.isDirectory dir))))

(defn make-something
  [& {:keys [dir] :or {dir "default-dir"}}]
  {:pre [(is (dir? dir))]}
  (println dir))

(make-something :dir "/tmp")
out => /tmp
ret => nil

(make-something :dir "/xxxx")
FAIL in clojure.lang.PersistentList$EmptyList@1 (form-init3332271312167175068.clj:1)
expected: (dir? dir)
actual: (not (dir? "/xxxx"))

AssertionError Assert failed: (is (dir? dir))  user/make-sth (form-init3332271312167175068.clj:1)