我有这样的事情:
user> (defrecord vertex [id val]) => user.vertex
user> (def v vertex) => #'user/v
user> (= v vertex) => true
user> (type v) => java.lang.Class
user> (type vertex) => java.lang.Class
user> (vertex. 1 2) => #user.vertex{:id 1, :val 2}
user> (v. 1 2) => "Unable to resolve classname v"
user> (new v 1 2) => "Unable to resolve classname v"
所以基本上我不能将顶点绑定到另一个名称。尝试将defrecord类型传递给函数,或者让或者其他任何东西都是一样的。 为什么会这样,我该怎么做才能临时重命名一个defrecord?
我猜这是与Java互操作有关的一些技巧。
答案 0 :(得分:4)
defrecord
生成一个Java类,我认为它实际上被视为Clojure中的一种特殊情况,特别是关于互操作(虽然我不是正面的)。
如果你的目标是能够轻松传递一个可以创建顶点的函数,那么解决方案是使用一个调用构造函数的本地函数,而不是自己进行互操作。
在Clojure 1.3中,deftype和defrecord自动生成另外两种方法:
->{type}
等同于构造函数map->{type}
将参数图作为参数对于上述情况,(->vertex 1 2)
和(map->vertex {:id 1 :val 2})
有效,并允许您进行后续构建。
如果您确实需要在传递它时可用的类,可能有些东西可以用宏来做,虽然我不确定。
答案 1 :(得分:2)
据我所知,这是不可能的。
如果你考虑defrecord如何运作;它实际上是字节码生成一个(java)类。当您在一个命名空间中执行defrecord并希望在另一个命名空间中使用它时,您可以看到这一点......
(ns my-first-namespace)
(defrecord Foo [x y])
(ns my-second-namespace
(:use my-first-namespace)
(:import my_first_namespace Foo)) ; still have to import the java class
; underlying the defrecord even tho
; the defining namespace is use'd (note
; hyphen / underscore changes).
不幸的是,java(实际上在JVM中)没有办法将类名别名为另一个类名。你可以得到的最接近的是子类化为一个新名称,但这相当粗略。