explain clojure dependencies slash syntax in project.clj? - clojure

In Clojure namespaces, I use slash to separate a namespace or namespace alias from a symbol in that namespace, as in
(ns whatever (:require [clojure.math.combinatorics]))
(clojure.math.combinatorics/subsets [42 43 44])
However, I just realized, looking at a project.clj, that slashes seem to mean something completely different in the dependencies section, as in
(defproject whatever "1.0.0"
:description (str "yeah sure yubetcha")
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.4.0"]
[org.clojure/math.combinatorics "0.0.3"]])
I don't usually have problems with dependencies: I just mindlessly scrape them from documentation and they get magically downloaded by Leiningen from clojars.org or the like. But I just realized that I don't understand the slash syntax here and would be grateful for a clarification, specifically if the usage is completely orthogonal to the usage of slash with namespaces or whether there is something more subtle going on.

The slashes in clojure code are for separating the namespace from the function name in the namespace. The slashes in project.clj are part of the name of the project (by convention organization/product) as used by maven.
A / is a valid element of a symbol - for example try 'this/is/not/a/namespace in the repl - it returns a symbol with a bunch of constituent slashes in it. The entire (defproject ...) form is inside an implicit syntax-quote (`), meaning you can have arbitrary names and they get treated as symbols (also you can use ~ to unquote and insert arbitrary code into project.clj, but this is usually a code smell).

Related

Why Clojure evaluates forms during AOT compilation?

I've set up small project:
project.clj:
(defproject testing-compilation "0.1.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.8.0"]]
;; this is important!
:aot :all)
src/core.clj
(ns testing-compilation.core)
(def x (do
(println "Print during compilation?")
1))
Then when I do lein compile in project directory I'm seeing output from a print:
$ lein compile
Compiling testing-compilation.core
Print during compilation?
My question is: why clojure evaluates top level forms during AOT compilation? Shouldn't they be evaluated at program startup?
For reference, Common Lisp doesn't evaluate forms by default and provides ability to tune this behaviour. Anything similar in Clojure? If nothing, does Clojure documentation explicitly state such behaviour?
UPD: Forms are evaluated at startup as well.
After specifying a main namespace and writing main function that prints Hello, world!, I did this:
$ lein uberjar
Compiling testing-compilation.core
Print during compilation?
Created testing-compilation-0.1.0-SNAPSHOT.jar
Created testing-compilation-0.1.0-SNAPSHOT-standalone.jar
$ java -jar target/testing-compilation-0.1.0-SNAPSHOT-standalone.jar
Print during compilation?
Hello world!
The first part of the AOT process is to find the file containing the main namespace and load it by evaluating every expression from top to bottom.
Some of these expressions will be require expressions that will have the effect of loading other namespaces, which recursively load yet more namespaces.
Other will be defn expressions that will have the effect of firing up the compiler and producing class files. One class file is produced for each function.
Other expressions may do some calculation and then do things that produce class files, so it's important to give them a chance to run. Here's a made up example:
user> (let [precomputed-value (reduce + (range 5))]
(defn funfunfun [x]
(+ x precomputed-value)))
#'user/funfunfun
user> (funfunfun 4)
14
It is possible to design a lisp that would not evaluate top level forms at start or, as you mention, make it optional. In the case of Clojure it was decided to keep a single evaluation strategy across both AOT and "non AOT" loading so programs always run the same regardless of how they are compiled. These are personal design choices made by others so I can't speak to their motivations here.

How to disambiguate in Clojure

I have this function in a namespace that does not import/require/use any other packages:
(defn crash [msg]
(throw (Throwable. msg)))
Cursive (the IntelliJ IDEA IDE Plugin) highlights Throwable and gives me the message Cannot disambiguate overloads of Throwable. I get the same message with Exception and Error.
I don't understand the source of this message - I doubt that these Java classes are defined in any other jar files apart from the Java language ones. Anything I can to make this message go away?
These are in the project.clj:
:dependencies [[org.clojure/clojure "1.6.0"]
[net.mikera/imagez "0.8.0"]
[org.clojure/math.numeric-tower "0.0.4"]]
Throwable has two 1-arg constructors (doc): one expecting a String and the other expecting a Throwable.
At runtime Clojure figures it out (since, in this specific case, it's impossible for an object to be both a String and a Throwable) but this requires the use of reflection.
Adding a type-hint to msg to specify which overload you expect to use would remove the need for reflection and hopefully calms Cursive down.
(defn crash [^String msg]
(throw (Throwable. msg)))

In Clojurescript how can I use multiple symbols or macros?

To "use" symbols in Clojurescript I often find myself having huge headers in clojurescript files, something like this:
(:use-macros
[webapp.framework.client.coreclient :only [defn-ui-component ns-coils write-ui read-ui]])
(:use
[webapp.framework.client.coreclient :only [log amend-record component-fn write-ui-fn]]))
:but I would like to have something more compact like in Clojure, so that I can just have:
(:use-macros [webapp.framework.client.coreclient])
(:use [webapp.framework.client.coreclient]))
How can I do this?
It is not supported and it seems that it won't be supported. "use" is considered a bad practice both in Clojure and ClojureScript as it makes the code less readable.

What does the idiomatic (defn -main ...) mean in a clojure program?

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.

Get available clojure namespaces

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)