Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exclude java.lang.* in Clojure namespace

Is there a possibility to exclude the classnames from java.lang in a Clojure namespace?

I need to use variables like Byte and String, and here the java.lang classnames come into my way.

maybe something like (ns my-ns (:exclude java.lang)) ?

like image 854
Dominik G Avatar asked Mar 18 '12 12:03

Dominik G


3 Answers

If you use the fully qualified name, there's no ambiguity. For example:

user=> (def user/Byte (java.lang.Byte/decode "0"))
#'user/Byte

After you've defined Byte in this way, Byte will resolve to your definition without the need to qualify the name

user=> Byte
0
like image 162
rplevy Avatar answered Nov 17 '22 09:11

rplevy


This is certainly possible if you manually remove the built-in mapping to java.lang.String before creating your own:

$ cake repl
repl-1=> (def String 1)
java.lang.Exception: Expecting var, but String is mapped to class java.lang.String (NO_SOURCE_FILE:1)
repl-1=> (ns-unmap *ns* 'String)
nil
repl-1=> (def String 1)
#'repl-1/String
repl-1=> String
1

I'll echo some of the other comments though, that defining something named String is not likely to make your life pleasant/convenient.

like image 33
amalloy Avatar answered Nov 17 '22 10:11

amalloy


I don't know the definitive answer to your question, but my educated guess is that you can't without modifying clojure itself. Here's my analysis:

The String symbol is interned in clojure/lang/Namespace.java as part of the default mappings (see the Namespace constructor in that class, which references DEFAULT_MAPPINGS in the clojure/lang/RT.java class). Interning means that there is a key in the member variable mappings of the Namespace class. The upshot of this is that every namespace starts with String mapped to String.class (see line 77 of RT.java in clojure 1.4.0).

In the ns macro, you can do something like:

(ns my-ns
    (:refer-clojure :exclude [<mapping to exclude>]))

but all that does is skip the code that interns new symbols (see line 3770 of clojure/core.clj in clojure 1.4.0), so it can't do anything to help you remove String from the namespace mappings.

Finally, if you attempt to redefine the mapping for String with something like a (defn String ...) the compiler will complain because String.class is not an instance of Var. See line 6797 of clojure/lang/Compiler.java in clojure 1.4.0 for details).

like image 1
Brian Cooley Avatar answered Nov 17 '22 09:11

Brian Cooley