3

我有这样的事情:

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 类型传递给函数、let 或其他任何东西也是如此。为什么会这样,我可以做些什么来临时重命名 defrecord?

我猜这是与Java互操作有关的一些技巧。

4

2 回答 2

4

defrecord生成一个 Java 类,我认为它实际上被视为 Clojure 中的一种特殊情况,特别是在互操作方面(尽管我并不肯定)。

如果您的目标是能够轻松地传递可以创建顶点的函数,那么解决方案是使用调用构造函数的本地函数,而不是自己进行互操作。

在 Clojure 1.3 中,deftype 和 defrecord 自动生成两个额外的方法:

  • ->{type}相当于构造函数
  • map->{type}将参数映射作为参数

对于上述,(->vertex 1 2)工作(map->vertex {:id 1 :val 2}),并让你做你所追求的建设。

如果您在传递它时确实需要可用的类,那么您可能可以使用宏来做一些事情,尽管我不确定。

于 2012-04-07T19:18:50.580 回答
3

据我所知,这是不可能的。

如果您考虑 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 中)没有办法将一个类名别名为另一个类名。您可以得到的最接近的方法是将子类化为一个新名称,但这很糟糕。

于 2012-04-07T17:13:52.813 回答