tags:

views:

300

answers:

2

So I'm trying to explore Clojure's internals and I've come across something I'm not quite sure I understand:

From the REPL, I can access RT.var("clojure.core","require") just fine (this is supposed to return the var associated with the "require" symbol in the "clojure.core" namespace):

user=> (clojure.lang.RT/var "clojure.core" "require")
#'clojure.core/require

However, if I try to access it in what I thought was the same way (

user=> (clojure.lang.Var/intern (clojure.lang.Namespace/findOrCreate (clojure.lang.Symbol/intern nil "clojure.main")) (clojure.lang.Symbol/intern nil "require"))
java.lang.IllegalStateException: require already refers to: #'clojure.core/require in namespace: clojure.main (NO_SOURCE_FILE:0)

I get an error that require already refers to something that exists. This is very strange because RT.var is the same as Var.intern, except with the arguments converted to a Namespace and Symbol respectively.

static public Var var(String ns, String name){
    return Var.intern(Namespace.findOrCreate(Symbol.intern(null, ns)), Symbol.intern(null, name));
}

I'll do some more digging, but I'm pretty stumped on this one. I've already checked: 1. nil is the same as null 2. I created var2, which returns the namespace argument sent to Var.intern, and var3, which returns the name argument sent to Var.intern. I then pass those two to Var.intern:

user=> (clojure.lang.Var/intern
(clojure.lang.RT/var2 "clojure.main" "require")
(clojure.lang.RT/var3 "clojure.main" "require"))
java.lang.IllegalStateException: require already refers to: #'clojure.core/require in namespace: clojure.main (NO_SOURCE_FILE:0)

Could this be a bug?

+2  A: 

This works fine:

(clojure.lang.Var/intern
 (clojure.lang.Namespace/findOrCreate
  (clojure.lang.Symbol/create "clojure.core"))
 (clojure.lang.Symbol/create "require"))

Symbol/intern works also:

(clojure.lang.Var/intern
 (clojure.lang.Namespace/findOrCreate
  (clojure.lang.Symbol/intern nil "clojure.core"))
 (clojure.lang.Symbol/intern nil "require"))
Michał Marczyk
AH yes... I was using clojure.main instead of clojure.core. Thanks!
Jieren
You're welcome! Incidentally, I used `Symbol/create` in place of `Symbol/intern`, but `intern` works too... I guess I'll better edit it in, lest it confuse some future visitor to this Question. :-)
Michał Marczyk
Symbol.intern() and Symbol.create() do basically the same thing tehse days. Originally create would expect interned string as argument, but this behavior was changed. Rich was thinking on getting rid of create() at some point in the future.
liwp
@liwp: Interesting! Thanks for posting this. :-)
Michał Marczyk
A: 

The REPL is just clojure.main, so we can not intern clojure.main/require in a REPL, but clojure.core/require, I think!

liumengjiang