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

欢迎!请参阅关于页面以获取更多关于如何工作的信息。

0
多方法

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

我的解决方案是简单地创建一个新的defmethod来处理java.lang.Integer。它与处理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)))

然后,对于任何满足 (integer? x) 返回 true 的 x 值,将调用具有调度值 :integerdefmethod

+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))
...