I would like to make my existing Clojure libraries usable from clojurescript as well as create new applications which run in both Clojure and Clojurescript.
I understand Clojure and Clojurescript have their differences, and that there are metaprogramming solutions such as cljx. But, I have limited my Clojure code to a compatible subset of Clojurescript and I would simply like to call clojure from clojurescript (and possibly vice-versa). I have seen this possible in libraries such as core.match, but I am unable to replicate what is done there.
I am currently getting No such namespace, I am not sure if it is because it is not possible, or because my namespacing or directory structure is wrong, or some other reason.
For concreteness, I have a directory structure of the form
src/
clj/
clopjys/
vector.clj
cljs/
cljdemo.cljs
I am trying to use vector.clj from within cljdemo.cljs, i.e:
(:require
[clophys.vector :refer [coords std-uniform-vector]])
My project.clj has the following entries
...
:source-paths ["src/clj"]
:cljsbuild {
:builds [{
; The path to the top-level ClojureScript source directory:
:source-paths ["src/cljs"]
...
You can't include clj code in cljs at runtime. The clj files will get included for the macros (which are defined in clj and is probably what you saw in core.match).
The best solution is cljx really, and if your code is actually compatible with clj and cljs then you will have a cljx file that will look exactly like a normal clj file. It is pretty simple and cool, try it out!
Since this question has been written, Clojure reader conditionals have appeared in the core language (whereas .cljx is a library).
Related
I need to share a namespace between my Clojure (Garden) and my ClojureScript (Reagent).
Currently the project folder looks like this:
src/
clj/
name/
css.clj
cljs/
name/
core.cljs
cljc/
name/
config.cljc
The config.cljc file has the following namespace: (ns name.config).
I've tried to reference this namespace from inside clj/name/css.clj with a require.
(ns name.css
(:require [name.config :as config]))
However, this results in a compile error from Garden.
Caused by: java.io.FileNotFoundException: Could not locate name/config__init.class or name/config.clj on classpath.
I guess it's not even checking for cljc files.
I added "src/cljc" to the :source-paths vector in project.clj and :garden :builds but I get the same error even after restarting the build processes.
I see this behaviour on Clojure 1.7.0 and 1.8.0.
It might also be worth mentioning that it works without issues in ClojureScript (with Figwheel handling the build). I can require and use the new namespace without problems.
It seems like I must be missing something really simple, because none of the documentation around .cljc files even mentions requiring them.
Check if you’re using Clojure 1.7 or above in your project.clj. This error message:
Caused by: java.io.FileNotFoundException: Could not locate name/config__init.class or name/config.clj on classpath.
indicates that you’re using Clojure 1.6 or below, as those versions of Clojure only know to look for .class or .clj files.
I got this same error when I moved a file from .clj to .cljc in my project. I did lein clean but that had no effect. Eventually I renamed the module namespace and that fixed it.
(My guess is that there was some sort of cache of compiled modules and it was referencing a module which no longer existed, but the cljc wasn't re-compiled because a module of that name was still cached.)
When I renamed the module namespace it worked, with no other changes to the code.
I have a project that works fine using lein run. Now I want to compile it into a standalone jar using lein uberjar. However, there are a couple of source files in my src/projectname/ directory called e.g. playground.clj and stats.clj that I use for experimenting with emacs & the repl, but that I don't want to compile for the final project.
With something like make, I would specify all files that should be compiled. With clojure/leiningen, it seems, all files are compiled by default - how can I exclude files? I haven't found anything in the leiningen docs.
I am currently using :aot :all. Is this the place to change something? Again, I couldn't find detailed documentation on this.
UPDATE:
The suggestions so far haven't worked. What has worked, however, is to include all desired namespaces instead of excluding the ones that should not be compiled. E.g.:
(defproject myproject "version"
;; ...
:profiles {:uberjar {:aot [myproject.data
myproject.db
myproject.util]}})
Have a look at leiningen's sample project.clj, which describes how to use :jar-exclusions or :uberjar-exclusions to exclude arbitrary paths when creating jars (resp. uberjars).
;; Files with names matching any of these patterns will be excluded from jars.
:jar-exclusions [#"(?:^|/).svn/"]
;; Files with names matching any of these patterns will included in the jar
;; even if they'd be skipped otherwise.
:jar-inclusions [#"^\.ebextensions"]
;; Same as :jar-exclusions, but for uberjars.
:uberjar-exclusions [#"META-INF/DUMMY.SF"]
Old question, but I think I found the answer for those coming after me.
I found the answer in the link to the sample leiningen project from #amalloy's answer, except instead of :jar-exclusions I use source-paths, here.
The idea is to create two separate source directories, one for stuff you don't care to spread around and one for stuff you do:
dev-src/<your-project>/playground.clj
dev-src/<your-project>/stats.clj
src/<your-project>/<everything-else>
Then, in your project.clj, include src in source-paths normally, and include emacs-src in a special profile where your want it visible, say the usual :dev profile:
{
;; ...
:source-paths ["src"]
:profiles {
:dev {
:source-paths ["src" "dev-src"]
}
}
}
That way when you're messing around on your machine those files will be in the jar, and when you deploy to clojars or compile with uberjar they will not be included in the jar, nor compiled.
Try this (ns ^:skip-aot my-ns)
You can also do
(ns ^{:skip-aot true} my-ns
(require [...]))
Source
I'd like to add certain library dependencies to LightTable as a whole so that when I am messing around learning new stuff, I don't have to create a new project as a whole.
Let's say I want to always have access to these libraries: math.combinatorics and math.numeric-tower.
Lighttable seems to be calling a repl from leinigen, so am I really needing to add something there?
See https://github.com/LightTable/LightTable/blob/master/project.clj
It will be calling a repl of Leiningen. Rather than adding the dependencies to LightTable you could add them to your Leiningen Profile (~/.lein/profiles.clj)
The file would probably look something like this with your dependencies:
{:user {:dependencies [[math.combinatorics "x.x.x"]
[math.numeric-tower "x.x.x"]]}}
Generally this is not a very good idea. It will be a global thing and will probably cause you problems in the future. If you create an application you might find that these two libraries are available when they won't be for other people or on difference computers.
What would be a better option would be to create a new project using Leiningen. You can then edit your project.clj file to look something like this
(defproject math-thing "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:dependencies [[org.clojure/clojure "1.6.0"]
[math.combinatorics "x.x.x"]
[math.numeric-tower "x.x.x"]])
Then when editing your clj file LightTable uses your project.clj file to start instrepl and will resolve any needed dependencies.
Use the leiningen profile e.g. ~/.lein/profiles.clj and define a :injections [ ... ] node which performs the (require '[ ]) and import, refer-clojure and other items you have. I generally prefer to have at least Alembic present in my dev profile (wrapping Maven/Sonatype) so I can download, install in maven then classpath and project reload in one go using a macro/function wrapper around distill* to prevent a long load time due to too many libraries included in the user space. Pretty much this is the only function I usually want present in any REPL or LT InstaRepl and I put development and debugging snippets in project ./dev/user.clj to keep most of the messy stuff project specific.
I am using a method from the contrib.string libraries but lein is having trouble finding the library.
In my project.clj I have :dependencies [[org.clojure/clojure "1.4.0"]] inside of defproject and then (use '[clojure.string :only (join)]) (use '[clojure.contrib.string :only (as-str)]) inside of src/file.clj
Do I need to add another dependency to include contrib? I have found examples of 1.2, but there seems to have been a shift and the documentation is, well, lacking.
Monolithic contrib is long gone, it had been split into several modules when clojure 1.3.0 was released. Now clojure.string belongs to standard clojure library. There are no as-str function in that namespace, but given its name I assume that you need str function.
UPD: I searched for as-str function and found that it works in the same way as str do, but takes only name of keywords and symbols, ignoring namespace and ':' keyword prefix. I think now you can do it only by writing the same functionality by yourself (I also had to do the same in my recent code).
the contrib.string is merged into clojure.string in clojure-1.4.0.
I'm new to Clojure and Leiningen, and I've determined that some of what I'll want to use is located in clojure.contrib.generic.math-functions. I found API information for that at http://richhickey.github.com/clojure-contrib/branch-1.1.x/math-api.html, but I can't find anything that helps me figure out what I should put into my project.clj file for that dependency.
I have tried [clojure.contrib.generic.math-functions "1.1"], [clojure.contrib.generic.math-functions "1.1.x"], and [clojure.contrib.generic.math-functions "1.1.0"]. For each of those, I get something like...
...
Caused by: org.apache.maven.artifact.resolver.MultipleArtifactsNotFoundException: Missing:
----------
1) clojure.contrib.generic.math-functions:clojure.contrib.generic.math-functions:jar:1.1
All clojure-contrib namespaces are shipped within a single jar file, for which the dependency has to be listed like:
[org.clojure/clojure-contrib "1.2.0"]
Please note that there are different versions available of that artifact. The 1.2.0 is the current stable release.
In order to use functions coming from the math-functions namespace in your clojure code, you need to either require or use such namespace, usually done within the ns form at the beginning of your source file:
(ns my.namespace
(:use [clojure.contrib.generic.math-functions]))
Have a look here to see the differences between use and require.
The next version of Leiningen will have a search task for precisely this purpose. It will search Clojars, Maven Central, and any other repositories your project has listed, provided they offer up downloadable indices. It's already implemented, so if you run Leiningen from git you can use it.
Also, the Leiningen tutorial covers this. Type "lein help tutorial".
You can generally find what you need at clojars.org - it's the default repository for leiningen. The current stable release of Clojure is 1.2.0, so you'd have this in your leiningen project.clj:
[org.clojure/clojure "1.2.0"]
[org.clojure/clojure-contrib "1.2.0"]
To use the generic math functions in your clojure, require or use it in your namespace declaration at the top of your source file:
(ns your-namespace
(:use [clojure.contrib.generic.math-functions :as mathf]))
This allows you to refer to the functions in that namespace like this:
(mathf/abs -10) ;; => 10
:use-ing namespaces with :as is the preferred way to use functions from other namespaces in your code. require is ok, but you'd have to prefix your functions with the entire namespace (e.g. clojure.contrib.generic.math-functions/abs) so that's not practical. Using a namespace without :as allows you to use these functions without any prefix at all (e.g. abs), but you're more likely to get namespace clashes and it might be difficult to see where functions come from, especially if you :use many libraries.
You can browse all libraries available from the default leiningen repository by checking out http://clojars.org/repo/. The structure of clojure-contrib will change when 1.3.0 is out, so you'll have to include the specific contrib library if you're using version 1.3.0-alpha-xx:
[org.clojure.contrib/generic "1.3.0-alpha4"]
Now that the clojure.contrib has been broken up, the math functions are in something called math.numeric-tower. The lein dependency is specified like this:
[org.clojure/math.numeric-tower "0.0.1"]
You can use or require as seems appropriate, for example
(use '[clojure.math.numeric-tower])