假设我定义了一个名为Node的记录:(defrecord Node [tag attributes children])
。
在此定义之后,根据defrecord
的{{3}}定义了一个名为->Node
的工厂函数,以及另一个工厂函数map->Node
和一个Java类构造函数{ {1}}。
我想知道位置工厂函数Node.
和构造函数->Node
,分开与正常差异之间究竟有什么区别一方面是Java类构造函数/方法,另一方面是clojure函数之间(通过正常差异我正在考虑这样的事情,即函数在Clojure中是一流的而不是方法)
答案 0 :(得分:8)
(更新:有关原始字段类型与ctor参数类型与工厂参数类型的参数类型的说明,请参阅此答案的结尾。)
位置工厂直接调用构造函数。除此之外唯一有趣的事情是对于具有大量字段的记录/类型(即超过20,这是Clojure函数可以接受的位置参数的最大数量)使得构造函数调用稍微复杂一些(因为你必须解压缩)来自rest-args seq的一些论点);由defrecord
和deftype
发出的位置工厂正确处理,并且检查是否提供了正确的参数数量,如果没有则抛出适当的异常。
私有函数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
特别存在,因为函数比构造函数更友好。