关于 Clojure 评估的说明

Clarification on Clojure evaluation

在 Clojure for the Brave and True 第 8 章中,提出了一个名为 if-valid 的函数(然后被拒绝)来抽象出验证检查的重复部分:

1
2
3
4
5
6
(defn if-valid
  [record validations success-code failure-code]
  (let [errors (validate record validations)]
    (if (empty? errors)
      success-code
      failure-code)))

作者解释说,在其上述状态下的函数将无法工作,因为 success-codefailure-code 将在每个 if-valid 调用上进行评估。我的理解是, if 函数的测试将返回真或假,这决定了成功或失败代码是否运行。请有人解释如何为每个 if-valid 调用评估 if 的 then 和 else 部分吗?


假设这个函数的使用如下:

1
2
3
(if-valid my-data validators
  (println"Data accepted")
  (throw (Exception."Bad data :(")))

这不好,因为函数参数在传递给函数之前必须先求值。因此,在此函数有机会运行验证之前,每次都会执行首先打印"数据已接受"然后抛出异常的副作用。