为什么Clojure defmulti调度函数收到0个args?

Why does Clojure defmulti dispatch function receive 0 args?

开始编辑:

Mea Culpa!我很抱歉。

我在Clojure 1.2.1的蛋糕代表中运行了此程序,说实话它没有用。现在,它在退出cake repl和cake编译之后就可以了,它也可以在1.3.0上运行。

结束编辑:

在以下情况中:我的调度函数正在传递零个args,但我不知道为什么。我已经测试了调度功能,它可以完成预期的工作。我将不胜感激任何建议。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
(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


该问题可能与defmulti的未记录defonce类似行为有关。

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

要在REPL中解决此问题,请删除多方法var (ns-unmap 'the.ns 'the-multimethod),然后重新加载名称空间(require 'the.ns :reload)

为避免此问题,您可以单独定义调度函数,然后将其var传递给defmulti,如下所示:

1
2
3
4
(defn foo-dispatch [...]
  ...)

(defmulti foo #'foo-dispatch)

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