如何在clojure中编写cond中使用的宏?

时间:2014-05-02 03:00:58

标签: macros clojure

我有以下宏来确保包含特定键的数据。

(defmacro with-correct-format
  [data & body]
  `(cond
    (nil? ~data) (throw (IllegalArgumentException.
                        "input data cannot be nil"))
    (nil? (:first-name data)) (throw (IllegalArgumentException.
                              "first name cannot be nil"))
    (nil? (:last-name data)) (throw (IllegalArgumentException.
                             "last name cannot be nil"))
    :else ~@body))

我想通过提取(nil? (:key data))条件来重构此代码。我尝试了这个,但没有工作:

(defmacro key?
  [key-name data]
  `((nil? (~key-name ~data)) (throw (IllegalArgumentException.
                             "cannot be nil"))))

我该怎么办?

2 个答案:

答案 0 :(得分:3)

一般来说,最好完全避免使用宏 - 这并不是真正需要采用宏形式的东西,所以坚持使用函数。

然后,您尝试捕获的内容将成为我们可以map结束的功能。

(defn check-data 
  [data]
  (if (nil? data)
      (throw (IllegalArgumentException. "input data cannot be nil."))
      (dorun (map #(when (nil? (% data)) (throw (IllegalArgumentException. 
                                                  (str % " cannot be nil"))))
                  [:first-name :last-name]))))

然后(带有正确格式的数据体......)就变成了(做(检查数据数据)体......)

请注意,使用宏,可以使用当前实现多次评估data的扩展。

答案 1 :(得分:1)

嗯,你没有向我们展示你如何使用key?或者"没有工作方式",但是(1)((nil? ...应该是{{1} }否则你正在调用(list (nil? ...)的结果,并且(2)你在第一个宏的nil?上缺少一些非引号~。但是,在这里没有要求宏......

data

(defn bar [data] 
  {:pre [(:first-name data), (:last-name data)]} 
  (println "This data passed:" (pr-str data)))