Record构造函数和位置工厂函数之间的区别

时间:2013-06-08 23:17:00

标签: clojure

假设我定义了一个名为Node的记录:(defrecord Node [tag attributes children])

在此定义之后,根据defrecord的{​​{3}}定义了一个名为->Node的工厂函数,以及另一个工厂函数map->Node和一个Java类构造函数{ {1}}。

我想知道位置工厂函数Node.和构造函数->Node分开正常差异之间究竟有什么区别一方面是Java类构造函数/方法,另一方面是clojure函数之间(通过正常差异我正在考虑这样的事情,即函数在Clojure中是一流的而不是方法)

2 个答案:

答案 0 :(得分:8)

(更新:有关原始字段类型与ctor参数类型与工厂参数类型的参数类型的说明,请参阅此答案的结尾。)

位置工厂直接调用构造函数。除此之外唯一有趣的事情是对于具有大量字段的记录/类型(即超过20,这是Clojure函数可以接受的位置参数的最大数量)使得构造函数调用稍微复杂一些(因为你必须解压缩)来自rest-args seq的一些论点);由defrecorddeftype发出的位置工厂正确处理,并且检查是否提供了正确的参数数量,如果没有则抛出适当的异常。

私有函数clojure.core/build-positional-factory的docstring中记录了这一点;在REPL上说(doc clojure.core/build-positional-factory)以阅读它,或(source clojure.core/build-positional-factory)查看来源。

最终结果大致如下:

;; positional factory for a type with up to 20 fields
(defn ->Foo
  "Construct a Foo."
  [x y z]
  (new Foo x y z))

;; positional factory for a type with many fields
(defn ->Bar
  "Construct a Bar."
  [a b c d e f g h i j k l m n o p q r s t & overage]
  (if (= (count overage) 2)
    (new Bar a b c d e f g h i j k l m n o p q r s t
             (nth overage 0) (nth overage 1))
    (throw
     (clojure.lang.ArityException.
      (+ 20 (count overage)) (name '->Bar))))))

关于参数类型的说明:

不确定这是否属于“正常差异”的标题,因此我将明确提及:deftype / defrecord引入的类可能包含基本类型的字段,在这种情况下相应的构造函数的参数也将是原始类型。但是,从Clojure 1.5.1开始,位置工厂总是采用所有 - Object参数,即使从技术上讲它们可以被声明为原始接受函数(即,如果涉及的基元类型是long和/或double并且最多有四个位置参数。)

答案 1 :(得分:2)

#{},空集。除了您明确表示您不感兴趣的差异外,没有其他差异。 ->Foo特别存在,因为函数比构造函数更友好。