I've just written some ClojureScript code, only to find out that I couldn't access one of the libraries listed in my project.clj's dependencies. Is this correct, i.e. that you can't use Clojure libraries from CLJS unless they're specifically designed to allow it?
If so, how much extra work is required to take a Clojure library that doesn't use any Java interop, and would itself be valid ClojureScript code, and make it useable from ClojureScript? From looking around GitHub, many libs appear to have separate source directories for clj and cljs code. Can such a library be added to my project.clj and be used immediately from either platform?
There are some ClojureScript differences from Clojure.
Dependecies from "project.clj" can be applicable / visible / usable by ClojureScript, for example, take a look at "jayq". You would include it in "project.clj":
(defproject xyz/xyz "0.1.0-SNAPSHOT"
:dependencies [[clj-time "0.4.3"]
[jayq "2.2.0"]
....
And then use it in the ClojureScript file:
(ns xyz.some.cljs
(:require ...
...
[clojure.browser.repl :as repl]
[jayq.core :as jq])
While "jayq" is not a "Clojure" library in the "backend" sense since it just wraps JavaScript, it is an example of using a "project.clj" dependency on the ClojureScript side.
In addition most of the core and several non core libraries are already ported to the ClojureScript side:
clojure.set
clojure.string
clojure.walk
clojure.zip
clojure.core.reducers
fold is currently an alias for reduce
core.match
core.logic (in works)
Other Clojure libraries will have to conform to the ClojureScript subset in order to work in ClojureScript.
It is worthwhile to clone ClojureScript repo and get a sense of what it supported (plus add your own features if you feel adventurous :)
ClojureScript dependencies are usually "front end" based (included the ones ported from backend). In other words, the end goal is to be compiled by V8 and run as JavaScript, hence anything that can be compiled by the ClojureScript compiler (repo above) can be used.
I see that the answers were given in 2013, but as of 2020, this is still the case with CLJS version 1.10. Its still not possible to use just any Clojure library, unless the library has been made CLJS compatible.Building with shadow-cljs will give build error like:
The required namespace "clojure.data.json" is not available, it was required by "bharati/binita/frontend/demo3/main.cljs".
"clojure/data/json.clj" was found on the classpath. Should this be a .cljs file?
I could not see any solution to that,other than using any other alternative library that is CLJS compatible.
Related
I am using Emacs and every time I start a Clojure REPL with cider-jack-in
, the minibuffer echoes the following:
Are you sure you want to run `cider-jack-in' without a Clojure project? (y or n)
I have a prior experience with Common Lisp and Slime. In this other lisp ecosystem, there is not such a thing. You just start Common Lisp without questions asked.
I do not get the purpose of this message from Cider. Probably, because I am missing something.
It is important to highlight that I do know how to create a Clojure project using lein command. I just do not get its relevance.
What am I missing for not using a Clojure project before starting the REPL?
Why is it so relevant?
What is the downside of developing a Clojure program with the .clj file, the REPL, doing some interactive programming, and re-compiling things as the program evolves with editions?
Just preventing problems with namespace?
Thanks
The main reason for using a "project", whether it is via a deps.edn file (for Clojure CLI tooling) or a project.clj file (for lein), is to provide the dependencies and hence the CLASSPATH. Since Clojure runs on the JVM, the CLASSPATH has to be set before the Java process is started. As an aside, this is not strictly true, but I'll ignore that complexity for now. The CLASSPATH is used by the JVM to find and then load classes during runtime.
If you're not using any dependencies then you can probably get away with not using a project.
I use emacs with cider and the Clojure CLI tooling myself. You might also want to look into the inf-clojure emacs package.
I am also coming from Common Lisp to Clojure and was confused a lot at the beginning.
And we use lein new because BraveClojure etc. shows this as the only way. Despite of its truths, it is too old. The Clojure community should write more up-to-date tutorials and books.
There is e.g. boot - the other build tooling tool than lein:
https://github.com/boot-clj/boot
Short intro:
https://jjmojojjmojo.github.io/boot-getting-started-with-clojure-in-10-minutes.html
Which allows you to start a repl with $ boot repl a repl with boot.user as the namespace
similar to CLUSER.
It is as powerful as lein.
And for command line scripting, there is babashka https://github.com/babashka/babashka
which is interpreted Clojure for scripting - callable even from the command line.
As some parts of Clojure are written in Java is there a way to look into these parts of source code from repl? I'm looking for something like this :
(source clojure.lang.Numbers/add)
As this part is implemented with Java
source prints Source not found and returns nil.
It depends on the environment you're using.
With plain REPL, you are quite limited.
Two most popular IDEs are Cursive and Emacs Cider.
As #Carcigenicate already pointed out, Cursive has an excellent Java support and allows you to jump to clojure java sources (or any other 3rd party lib sources - providing the sources have been published) easily.
It also allows you to debug Clojure compiler itself quite easily.
Emacs Cider has some support for Java.
Out of the box you can jump to JDK sources (with some caveats, see https://github.com/clojure-emacs/cider/issues/2687).
For other artifacts (like clojure.lang itself or other 3rd party java libs) you should be able to jump to the source code as long as you add the corresponding source jar to :resource-paths (assuming leiningen-based project here).
See here for more info about Cider's support.
As I understand most clojure and java libraries can be included in cljs code. How does the cljs compiler accomplish this ?
I understand that if I have a source file, the cljs compiler takes the source and outputs javascript. However how about if I am using java libraries such as joda-time for which I have included its clojure wrapper clj-time. So in this case it only has the java byte code for joda-time. So how will the cljs build tool, generate js code from the byte code of the java jar (joda-time)?
As I understand most clojure and java libraries can be included in cljs code. How does the cljs compiler accomplish this ?
You are mistaken. Many clojure libraries can be compiled for CLJS, with only minimal changes (sometimes even none), but there is no way to use classfiles: it must be .clj source files, compiled to javascript instead of to classfiles.
You cannot use Java libraries in cljs code.
I've found two ways of compiling Clojure *.clj files into *.class files, and while they both work, I have some gripes with both of them.
The first one uses a REPL and so cannot be automated (or can it?)
The second one uses lein. To be frank I don't see why I should use a dependency management tool for something that should be part of the core tool-chain of the language. But in any case, using lein soon forces you to use a local Maven repository if your Clojure code needs to access local jars (which is highly likely).
Is there a better way to generate *.class or *.jar files from Clojure code that involves only core Clojure tools and that can be employed in a scripted, non-interactive way?
Clojure provides clojure.core.Compile, which can be used to compile Clojure code from the command-line.
java -Dclojure.compile.path=<targetdir> -cp <targetdir>;clojure.jar <list of namespaces>
For an example of how to use this from ant, look at the compile-clojure task in Clojure's own build.xml file.
clojure.core/compile can be automated via Clojure
I am asking this question to straighten out a confusion I have about project.clj :dependencies and modules specified using :use/:require.
I use lein to build. I want to write a Clojure project and perhaps other than its being dependent on a particular Clojure release, do not want the project to be dependent on any module's particular version.
For example:
(defproject bene-csv "1.0.0-SN"
:description "A csv parsing library"
:dependencies [[org.clojure/clojure "1.3.0"]
[clojure-csv/clojure-csv "1.3.2"]])
I don't particularly need to be dependent on clojure-csv 1.3.2. My code will will work with whatever version there is.
Am I required to specify a dependency so a version is fetched locally?
If not, what other mechanisms are there to get the modules I need and where would they
be located?
Thank You.
I believe leiningen uses the same versioning system as maven. See Keeping dependency versions up to date in Leiningen projects and How do I tell Maven to use the latest version of a dependency?.
Telling Leiningen "just pull in whatever version you like; I don't care" is just asking for trouble down the road. Repeatability the foundation of automation: https://github.com/technomancy/leiningen/wiki/Repeatability