请在2024年Clojure调查!中分享您的想法。

欢迎!请查阅关于页面了解更多关于这里是如何工作的信息。

0
多方法

似乎 (?) Clojure将所有整数实例化为java.lang.Long。我最近发现我使用的一个库(该库包装了一个Java库)返回的是java.lang.Integer。这打破了我正在使用的一个多方法,该方法是按类来分发的。

我的解决办法是简单地创建一个新的defmethod来处理java.lang.Integer。它与处理java.lang.Long的defmethod完全相同。

是否有更优雅的方法?能否使defmethod处理一组分发值?Integer和Long有一个共同的祖先类java.lang.Number,但我不想使用它,因为它会捕捉浮点数,而浮点数应该被忽略。

我想我可以重写分发以检查输入类的类型是Integer还是Long,并以此分发到:int,然后以:string的形式分发java.lang.String,但这实际上可能需要更多的代码:)

当前的形式大致如此:

 (defmulti int-or-nil class)

(defmethod int-or-nil java.lang.Long
  [integer]
  (identity integer))

(defmethod int-or-nil java.lang.Integer
  [integer]
  (identity integer))

(defmethod int-or-nil java.lang.String
  [maybe-int-string]
  (try (Integer/parseInt maybe-int-string)
       (catch java.lang.NumberFormatException e)))

(defmethod int-or-nil :default
  [not-int])

2 条回答

+1

选中
 
最佳回答

Clojure 允许您使用任何选择的分发函数来编写 defmulti 定义,而不仅仅是像您在示例中显示的 class

您可以选择类似这样的分发函数

(defn my-dispatch-fn [x]
  (if (integer? x)
    :integer
    (class x)))

然后当 defmethod 的分发值为 :integer 时,任何满足条件 (integer? x) 返回 true 的值 x 都会被调用。

+1

您可以在自定义层次结构中为 Long 和 Integer 提供一个共同祖先级别,然后将其绑定到多方法上。

(def h (-> (make-hierarchy)
           (derive Long :num)
           (derive Integer :num)))
(defmulti yy type :hierarchy #'h)
(defmethod yy :num [x] (format "%o is a num" x))
(defmethod yy :default [x] "I don't know")
(yy 7)
(yy (Integer. 42))
...