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

欢迎!请查看关于页面以了解更多关于本网站的信息。

0
多方法

看起来(?)Clojure将所有整数实例化为java.lang.Long。我最近发现我使用的库(该库封装了一个Java库)返回的是java.lang.Integer。这破坏了我一个基于类进行派发的方法。

我的解决方案是简单地为java.lang.Integer创建一个新的defmethod来处理。它与处理java.lang.Long的defmethod完全一样。

有没有更优雅的方式来处理这个问题?能否创建一个defmethod来处理一组派发值?整数和Long有共同的父类java.lang.Number,但我不想使用它,因为它会捕获浮点数,而浮点数不应该被捕获。

我想我可以重新编写派发以检查输入值是Integer还是Long,然后按:int进行派发,并将java.lang.String作为: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)))

然后,具有派发值 :integerdefmethod 将会在任何满足 (integer? x) 返回 true 的 x 值上被调用。

+1

你可以在一个与 multimethod 相连接的自定义层次结构中为 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))
...