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天的时间试图找出如何使用“命名参数”创建新记录。