Is there an idiomatic way to get available namespaces that can be used?
(all-ns) returns only already used namespaces. (Package/getPackages) returns all Java packages available for import, but only those Clojure namespaces that are already used.
Then I stumbled upon this post, but it uses some classpath magic.
So I want to get something like ('clojure.core 'clojure.set ... 'clojure.contrib.accumulators 'clojure.contrib.condition ...) if I have the clojure.jar and contrib.jar on my classpath, but I haven't used anything yet.
You will need to do "classpath magic". Since there is no kind of registry, you have to walk the classpath and look in every clojure source file to determine what namespaces are available. (In case the files are not AOT compiled. Otherwise you'll need a different heuristic.)
I think the function used in the linked post is the best way to go: clojure.contrib.find-namespaces/find-namespaces-on-classpath.
Deprecated since Clojure 1.3.0; use now clojure.tools.namespace.find/find-namespaces and clojure.java.classpath/classpath from http://github.com/clojure/java.classpath
I have found bultitude to be a great tool for doing this.
Example:
user=> (require '[bultitude.core :as b])
nil
user=> (take 10 (b/namespaces-on-classpath))
(bultitude.core-test bultitude.core clojure.data clojure.string clojure.test clojure.xml clojure.inspector clojure.repl clojure.set clojure.test.junit)
user=> (b/namespaces-on-classpath :prefix "bultitude")
(bultitude.core-test bultitude.core)
Related
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?
I apologize if the question is trivial, but some googling is not leading me anywhere. What is the general syntax of defmulti and defmethod? I can write simple multimethods, but I am not sure where I can put the docstring, pre and post conditions, metadata and so on.
I am actually interested in ClojureScript more than in Clojure, so if there are differences between the two, please tell me.
In a REPL you can use the doc function to get the function arguments and (most of the time) an explanation of the options. As for ClojureScript, these two functions are macros, which means they are expanded at compile time and should behave exactly as they do in regular Clojure. That is, as long as ClojureScript can handle the code the macro generates.
user=> (doc defmulti)
-------------------------
clojure.core/defmulti
([name docstring? attr-map? dispatch-fn & options])
Macro
Creates a new multimethod with the associated dispatch function.
The docstring and attribute-map are optional.
Options are key-value pairs and may be one of:
:default the default dispatch value, defaults to :default
:hierarchy the isa? hierarchy to use for dispatching
defaults to the global hierarchy
nil
user=> (doc defmethod)
-------------------------
clojure.core/defmethod
([multifn dispatch-val & fn-tail])
Macro
Creates and installs a new method of multimethod associated with dispatch-value.
nil
At Clojuredocs: defmulti, defmethod.
If you don't find the examples there detailed enough, you might consider adding your own (once you've gotten all your questions answered).
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])))
I'm familiar with packages from e.g. Java and Lisp, but what I'm seeing in other people's code is some apparent idioms like calling the entry point '-main' and using a backtick for the namespace name in (in-ns `foo), that kind of thing. I don't see these spelled out anywhere in docs or tutorials. Is there some resource which explains such conventions around structuring programs?
Edit:
I think I must have picked up the backtick thing from this answer: Splitting a Clojure namespace over multiple files, which I stumbled across while trying to make sense of (defn -main ...). Given the author, I took it as best practice. However, now that I poke around in the Clojure sources he cites, I see that only the regular quote is used. I guess most likely it's a typo.
(Narrowed the scope of the question title accordingly)
The default for gen-class is to use - as the prefix for method names of that class. Which is why -main is the default entry point for java -cp clojure.jar yourclass
Backticks qualify their argument with the current namespace, so (in-ns `foo) is the same as (in-ns 'current-namespace/foo) and I don't think that's particularly idiomatic. The idiomatic way is to put each namespace in its own file with (ns ...) at the top, and use or require them as needed.
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 ...