I am trying to figure out the difference between clojure.lang and clojure.core.
For instance, the in-ns function is in clojure.lang
> in-ns
=> #< clojure.lang.RT$1#bc647a2>
But the create-ns function is in clojure.core
> create-ns
=> #<core$create_ns clojure.core$create_ns#6945af1f>
And while I can do ns-interns on clojure.core, to know what belongs to it
> (ns-interns 'clojure.core)
=> {sorted-map (var clojure.core/sorted-map), ... }
It won't work with clojure.lang
> (ns-interns 'clojure.lang)
Exception No namespace: lang found clojure.core/the-ns (core.clj:3760)
And unfortunately, in the documentation, everything appears as if it was part of clojure.core
(example1, example2)
Now, I am trying to implement a new language on top of clojure.lang, so I used create-ns to get a namespace that doesn't have clojure.core (but it does have clojure.lang, which makes sense). But then I wanted to know what clojure.lang had, and I couldn't figure out what was in clojure.core vs clojure.lang.
So what is in clojure.lang?
EDIT:
As cgrand shows below, it happens that in-ns is also part of the clojure.core namespace. But that doesn't tell what I wanted to know.
Which is: when I make a new empty namespace with (create-ns 'name-of-namespace), which functions and macros are defined in it?
clojure.lang is a java package containing implementation classes for Clojure.
clojure.core is the clojure namespace defining the core of the language.
When you see #< clojure.lang.RT$1#bc647a2> it just means that in-ns holds something that is anonymously defined in clojure.lang.RT.java. However:
=> (meta #'in-ns)
{:added "1.0", :ns #<Namespace clojure.core>, :name in-ns, :doc "Sets *ns* to the namespace named by the symbol, creating it if needed.", :arglists ([name])}
demonstrates that in-ns belongs to clojure.core.
You can get a list of all symbols defined in a namespace by using ns-map.
That will show all symbols defined in a namespace.
`(keys (ns-map 'namespace))`
To show all functions (not macros) in a namespace.
`(filter #(ifn? %) (keys (ns-map 'namespace)))
Related
I came across this problem after creating a new namespace.
Here is the code:
(create-ns 'my-new-ns)
=> #object[clojure.lang.Namespace 0x7c7c8359 "my-new-ns"]
(in-ns 'my-new-ns)
=> #object[clojure.lang.Namespace 0x7c7c8359 "my-new-ns"]
(reduce + [1 2 3])
CompilerException java.lang.RuntimeException: Unable to resolve symbol: reduce in this context, compiling:(/private/var/folders/pg/bynypsm12nx1s4gzm56mwtcr0000gn/T/form-init1425759900088902804.clj:1:1)
As you can see reduce function is not defined in my-new-ns namespace.
I should be able to create new namespaces so What would be the best solution for this problem?
P.S: Also, I'm trying to create those namespaces for my users so they will be able to do whatever they want in their namespaces(the idea is like a container) and creating isolation between namespaces.
clojure.core functions are not special in their need to be referred to make them available for unqualified use. The ns macro does several things:
creates the namespace - create-ns
changes the current namespace to that namespace - in-ns
automatically refers all of the clojure.core vars into the new namespace - refer-clojure
You can always use the qualified form of the core function (unqualified is just less typing), so when you get in this situation, this simple call will get you right again:
(clojure.core/refer-clojure)
Instead of creating namespace manually and then switching to it, I'd recommend using ns macro. According to the doc:
Sets *ns* to the namespace named by name (unevaluated), creating it if needed.
Also it will load all public vars from clojure.core to newly created namespace.
So, basically this
> (create-ns 'my-new-ns)
> (in-ns 'my-new-ns)
> (clojure.core/refer 'clojure.core)
is equal to this
> (ns my-new-ns)
Update:
Answering your question: symbols from standard library are not referred in newly created namespace, that's why you cannot access them without qualifier:
> (create-ns 'x)
> (in-ns 'x)
> reduce ;; throws "Unable to resolve symbol"
> clojure.core/reduce ;; works fine
You need to refer those symbols manually by calling (clojure.core/refer 'clojure.core).
Your new namespace needs to use the "standard" namespaces to be able to resolve names in them. The documentation indicates that this would be java.lang, clojure.lang.Compiler and clojure.core.
I guess you are supposed to use
(ns my-new-ns)
instead. create-ns is a low-level facility.
Imagine there is the following require-statement inside a namespace:
(ns my.core
(:require '[mylib.sth :as thing]))
(def somevar 123)
Is there a way to access mylib.sth via thing also from outside this namespace? I mean to somehow get the same behavior as for the definition somevar:
(ns somethingelse)
my.core/somevar
;; =123
(my.core/thing/myf "param") ;; something like this
;; ...
resolve and ns-resolve were made for this situation.
They will return nil if the symbol is not found, otherwise they return the var, which you can deref in order to get the current bound value.
user=> (ns my.test)
nil
my.test=> (def hidden 5)
#'my.test/hidden
my.core=> (ns my.core (:require [my.test :as t]))
nil
my.core=> (in-ns 'user)
#object[clojure.lang.Namespace 0x25930632 "user"]
user=> #(resolve 'my.test/hidden)
5
user=> #(ns-resolve 'my.core 't/hidden)
5
This works, but it's also a last resort. It should be reserved for situations where you are writing code that uses namespaces and bindings that you expect to find at run time that cannot be accessible at compile time. For example I use resolve to avoid transitive AOT of my project while compiling a stub that is callable from Java; the stub -main invokes require and then resolve at runtime, using the resolved values to access the real code.
If all you are looking for is a convenience or syntactic shortcut, the better option is to explicitly require a namespace if you want to use its values.
Simple as the headline suggest:
Why do I have to
(require 'clojure.edn)
in order to use e.g.:
(clojure.edn/read-string "9")
And why can I immediately invoke:
(clojure.string/join (range 4) "-")
Clojure programs start at the top of the "main" namespace (often project-name.core) and evaluate each form from top to bottom. This happens when the program starts, and before any "main" functions are invoked.
When a require expression is evaluated it jumps over to that namespace and does the same thing there. If requires are encountered there it recurses down branches of those namespaces, recursively loading each namespace as required.
So If you don't explicitly state that your namespace requires another namespace, then you are at the mercy of the order that other namspaces you require load their dependencies. Sometimes it will work, and sometimes unrelated changes to the evaulation order of your distant dependencies will break your code.
So please, please, ... declare your own requirements!
in the repl (just starting clojure) I have the following ns loaded by default
user=> (pprint (map #(.getName %) (all-ns)))
(clojure.edn
clojure.core.server
clojure.java.io
clojure.java.shell
clojure.core.protocols
clojure.string
clojure.java.browse
clojure.pprint
clojure.uuid
clojure.core
clojure.main
user
clojure.java.javadoc
clojure.repl
clojure.walk
clojure.instant)
in whichever namespace you are in, clojure.edn seems not to be loaded
If I have a symbol who's namespace is an alias, like q/w, how can I find its actual namespace, say actual.namespace/w ?
I know that resolve will give me the fully qualified var, but I don't know how to get the namespace of a var.
The best I can do is:
(defn fqns [s] (str (get (ns-aliases *ns*) (symbol (namespace s)))))
surely there's a simpler way ?
You can get the namespace object of a symbol as shown below (if you want name of ns as string then just call str at the end):
(defn fqns [s] (->> (resolve s) meta :ns))
The symbol itself has no direct connection to any namespace object; its namespace part is just an interned string. It is only when it's being resolved that this string is treated as the name of an actual namespace in which to look up a Var. (In particular, you can create a symbol foo/bar without creating a namespace foo or registering foo as an alias for a namespace.) Thus, you need to either go through resolve or do part of its work yourself.
In the first case, you can say (in recent versions of Clojure; or you can skip the hyphens signifying property access -- instead of -ns, use ns -- to be backwards compatible)
(.. (resolve s) -ns -name)
This resolves a Var object, then extracts a reference to its namespace from its ns field and finally extracts the symbolic name of the namespace from its name field. (Note that the namespace and name functions wouldn't work, since Vars and namespaces do not implement clojure.lang.Named.)
The function from the question text is fine too, although it'll be better to extract the symbol name from the namespace -- (.-name (get ...)) -- rather than rely on the toString representation of namespaces through the use of str.
You may also want to add clojure.lang.Var and clojure.lang.Namespace type hints to avoid reflection in your calls. (If you want them to be faster, or if you need *warn-on-reflection* to tweak something else for performance and wish to avoid useless warnings here.)
If you wish to handle the possibility that the namespace does not exist (and return nil in that case, in keeping with usual Clojure idiom):
(defn fqns
([s]
(fqns (.-name *ns*) s))
([ns s]
(some-> ns
find-ns
.-name
ns-aliases
(get (symbol (namespace s)))
.-name)))
Or use some if-lets in Clojure 1.4 and earlier.
I was reading Clojure in Action chapter 8 about TDD and experimented with the stubbing macro. It uses the dynamic binding mechanism to stub functions. Alas, in Clojure 1.3 it is not possible to use the binding mechanism for non-dynamic vars, so the stubbing macro doesn't work in most cases, unless you explicitly declare the var which points to a function dynamic. Then I wondered how stubbing is done in Midje and tried to find the source for 'provided', but I couldn't find it. So here it goes:
How is 'provided' implemented in a fact in Midje? Can someone explain this in detail?
Clojure 1.3 provides a with-redefs macro that works even with vars that haven't been declared dynamic:
user=> (def this-is-not-dynamic)
user=> (with-redefs [this-is-not-dynamic 900] this-is-not-dynamic)
900
For backward compatibility, Midje uses its own version, whose guts look like this:
(defn alter-one-root [[variable new-value]]
(if (bound? variable)
(let [old-value (deref variable)]
(alter-var-root variable (fn [current-value] new-value))
[variable old-value])
(do
(.bindRoot variable new-value)
[variable unbound-marker])))