Java 为什么可以';我不能在clojure中绑定一个记录吗?

Java 为什么可以';我不能在clojure中绑定一个记录吗?,java,clojure,interop,Java,Clojure,Interop,我有这样的想法: 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)

我有这样的想法:

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互操作有关的一些技巧。

据我所知,这是不可能的

如果你想一想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中)没有办法将一个类名别名为另一个类名。最接近的方法是将子类化为一个新名称,但这相当糟糕。

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

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

在Clojure 1.3中,deftype和defrecord自动生成两个附加方法:

  • ->{type}
    等价于构造函数
  • map->{type}
    将参数映射作为参数
对于以上内容,
(>vertex12)
(map->vertex{:id 1:val 2})
起作用,并允许您进行所需的构造


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

这是有道理的,尽管我有点喜欢在clojure中可以重新定义/重命名几乎任何东西,所以我很惊讶我不能将类名绑定到局部变量,特别是当
(=v vertex)时
返回
true
太棒了!非常感谢您的分享:我花了3天的时间试图找出如何使用“命名参数”创建新记录。