Why can't I bind defrecord in clojure?
I have something like this:
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"
So basically I cannot bind a vertex to a different name. It's the same with trying to pass the defrecord type to a function, or let, or whatever. Why is this, and what can I do to temporarily rename the defrecord?
I guess this is a Java interop related trick.
defrecord
generates a Java class, which in my opinion is actually viewed as a form of special case in Clojure, specifically with regard to interoperability (although I'm not sure).
If your goal is to be able to easily bypass a function that can create vertices, then the solution is to use a local function that calls the constructor rather than doing the interop itself.
In Clojure 1.3, deftype and defrecord automatically generate two additional methods:
-
->{type}
equivalent to constructor -
map->{type}
takes a map of arguments as an argument
For the above, (->vertex 1 2)
both (map->vertex {:id 1 :val 2})
work and allow you to complete the construct you are doing.
If you really want a class that is accessible as you go through it, there might be something you can do with macros, although I'm not sure.
This is not possible as far as I know.
If you are thinking about how defrecord works; The bytecode actually generates the (java) class. You can see this in action when you do defrecord in one namespace and want to use it in another ...
(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).
Unfortunately, in java (really in the JVM) there is no way to list a class name to another class. The closest you can get is subclassing to the new name, but that's pretty crude.