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.
Related
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
I am trying to create a DSL for packaging software using clojure. I want to define macros, functions, etc. and then load a file, and I want all of those things I define to be in the same namespace as the file itself, so that if I define a macro abe, I can use it in the file without using abe's fully qualified name.
I have this so far:
(binding [*ns* (find-ns 'my-namespace)]
(load-file "Myfile"))
But I get the feeling I'm doing it wrong.
Also, it would be nice to even have locally bound variables accessible within the clojure file. Something like this:
(let [a 1]
(binding [*ns* (find-ns 'my-namespace)]
(load-file "myfile")))
Where a is usable from within myfile.
The idea is to allow a programmer to specify how to package something in real clojure, but with the language extended in ways that are transparent to the programmer.
Is there a better way to do this? Is there some better "idiomatic" way of creating a DSL in clojure?
According to spec, def should intern the var in the current ns (i.e. *ns*). However, the following code does not look anything like it:
(ns namespace-b)
(defn def_something []
(ns namespace-a)
(println *ns*) ;prints namespace-a as it should
(def something 1)
)
(def_something)
(println namespace-b/something) ; prints 1
(println namespace-a/something) ; throws
What am I missing?
Notes:
defn is used just for clarity. Defining and running anonymous function works just as well.
I know that using def inside function is probably not very idiomatic. However, this is just extracted essence of a bigger problem I ran into.
The parser already interns the var to the current namespace at compile time, although it won't be bound immediately:
(defn dd [] (def x 0))
x ;; => #<Unbound Unbound: #'user/x>
The relevant piece of code can be found here, with the second parameter to lookupVar triggering the aforementioned interning for non-existing vars here.
The parses then generates an expression that references the previously created var, so the expression logic never leaves the current namespace.
TL;DR: def is something that the compiler handles in a special kind of way.
The key thing to understand about def is that it is a macro. This means that it does not resolve the namespace or create the binding at runtime, but beforehand, while the code is being compiled.
If you call a function that calls def, that call to def was already resolved to use the namespace in which the function was defined. Similarly, if you call functions inside a function body, the functions to call are resolved at compile time within the namespace where that function was defined.
If you want to generally bind values to namespaces at runtime, you should use the function intern, which lets you explicitly set the namespace to mutate.
All this said, namespace mutation is just that, it's procedural and is not thread safe and does not have nice declarative semantics like other options Clojure makes available. I would strongly suggest finding a way to express your solution that does not involve unsafe runtime mutation.
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)))
Would it be possible to override the 'require' command so that it will try to download a certain resource if it was not found on the local machine. For example:
(require 'examples.introduction)
; if not found => download from the net
; (url: http://media.pragprog.com/titles/shcloj/code/examples/introduction.clj)
You could override the require function and of course the overriden variant could download stuff if the namespace it was asked for is not available on the classpath. Overriding the way :require works in (ns ...) forms is, AFAIK, impossible for now due to the way in which ns is handled.
Note that such a 'downloading require' wouldn't be very helpful if you wanted to place new paths on the classpath (including new jars), as classpath injection doesn't work reliably in Clojure (due to JVM issues). There is clojure.core/add-classpath... but it's been marked as deprecated since forever now, its use is strongly discouraged, there are no guarantees that it will work for you and this situation isn't likely to change anytime soon. On the other hand, if you wanted to put new source files in a directory which was already present on the classpath, then that should work fine.
In case you do want to play around with overriding require, if you have a foo namespace, you could do
(ns foo
(:refer-clojure :exclude [require])
; other stuff; any :requires here will work as usual!
)
Then define your own require, using clojure.core/require when appropriate:
(defn require [ns-symbol]
(do-stuff-to-obtain-the-namespace))
clojure.contrib.find-namespaces namespace might be helpful in finding out what's available on the classpath. (Or you could use the the-ns function and see if it throws an exception after an initial attempt at requiring the namespace through clojure.core/require.)
Note that the binding approach which might come to mind first ((binding [require ...] ...)) will not work, since require normally resolves to a Var interned in the clojure.core namespace and Vars from namespaces whose names start with clojure are currently directly linked by the compiler (meaning no actual Var lookup is performed at runtime, so rebinding of those Vars has no effect on the code).
The (:refer-clojure :exclude [require]) in the ns form for your namespace prevents require from resolving to clojure.core/require and leaves you free to define a Var of that name in your own namespace. As mentioned above, that doesn't prevent the clojure.core/require Var from being accessible if you type out the fully qualified the symbol.
Actually, (add-classpath "http://foo/bar/baz/src/") or (add-classpath "http://www.foo.com/bar.jar"), will allow requiring remote stuff.
MichaĆ's warnings do apply though: Only use this for toying at the repl ...