为什么Clojure defmulti dispatch函数接收0参数?

时间:2011-12-19 17:27:42

标签: clojure

开始编辑:

Mea Culpa!我道歉。

我在Clojure 1.2.1的蛋糕代表中运行它,它老实说不起作用。现在它在退出蛋糕repl和蛋糕编译之后做了,它也在1.3.0工作。

结束编辑:

在下面:我的调度函数正在传递零参数,但我无法弄清楚原因。我已经测试了调度功能,它完成了应有的功能。我很感激任何建议。

(defrecord AcctInfo [acct-type int-val cur-bal])
(def acct-info (AcctInfo. \C 0.02 100.00))
ba1-app=> acct-info
ba1_app.AcctInfo{:acct-type \C, :int-val 0.02, :cur-bal 100.0}

(defn get-int-calc-tag [acct-type]
    (cond   (= acct-type \C) :checking
            (= acct-type \S) :savings
            (= acct-type \M) :moneym
            :else            :unknown))

(defmulti calc-int (fn [acct-info] (get-int-calc-tag (:acct-type acct-info))))

(defmethod calc-int :checking [acct-info] (* (:cur-bal acct-info) (:int-val acct-info)))

ba1-app=> (get-int-calc-tag (:acct-type acct-info))
:checking

ba1-app=> (calc-int acct-info)
java.lang.IllegalArgumentException: Wrong number of args (0) passed to: ba1-app$get-int-calc-tag

1 个答案:

答案 0 :(得分:11)

问题可能与defonce的无证defmulti行为有关。

如果您重新加载包含(defmulti foo ...)表单的命名空间,则defmulti将不会更新。这通常意味着不会更新调度函数,但所有方法实现(在同一名称空间中)都将更新。 (如果defmulti foo ...) var已绑定到值,则foo不执行任何操作。

要在REPL中修复此问题,请删除multimethod var (ns-unmap 'the.ns 'the-multimethod),然后重新加载命名空间(require 'the.ns :reload)

要防止出现此问题,您可以单独定义调度功能,并将其var传递给defmulti,如下所示:

(defn foo-dispatch [...]
  ...)

(defmulti foo #'foo-dispatch)

当代码看起来像这样时,如果您对foo-dispatch进行更改,则足以重新加载命名空间。