I'm trying understand how declare and require namespaces through lein. I created a project "interview", and inside "src/interview" I have a folder called "prompts", it has a file called rawlist.clj:
+ /interview project root
|--+ /src lein src
| |--+ /interview
| |--+ core.clj
| |--+ /prompts my new folder
| |--+ rawlist.clj
rawlist.clj file:
(ns interview.prompts.rawlist)
;...
questions:
How require rawlist in repl?
I'm trying (require 'interview.prompts.rawlist)
How require use some function of rawlist?
How correct create a test folder for this?
See the clojure docs for require. Here's an example where the namespace is given the alias r so that you can shorten the names.
(require [interview.prompts.rawlist :as r])
(r/your-function)
You can also refer to the full name at any time too:
(interview.prompts.rawlist/another-fn)
There are many ways to use require, e.g. with refer if you don't want a prefix. Say you have 3 functions f1,f2,f3, then you can refer to them in these ways:
(require [interview.prompts.rawlist :refer [f1 f2] :as r)
(f1)
(f2)
(r/f3)
Notice in third case, because it wasn't in the refer list, you have to use the r prefix.
For test folders, read the documentation for leiningen where it is explained, but basically boils down to:
+ /interview
|--+ src/
|--+ test/
and the sub-folder structure follows exactly the same pattern as the src dir.
You can add additional folders in project.clj using :source-paths and :test-paths keys in the main project macro. See the sample project for more information.
I recommend you absorb everything in the sample project above, and also read the leiningen tutorial.
Finally, when referring to functions in the ns declaration in other sources (e.g. in your tests) you use the same format, but using the :require form:
(ns foo.bar
(:require [interview.prompts.rawlist :as r]))
(r/foo-fn)
Related
I have create a project with two files core.clj and module.clj.
On core.clj to be able to use function of module.clj I have declared :
(ns my-project.core
(:require [my-project.module :as mod]))
And on module.clj to be able to use function of core.clj I have declared :
(ns my-project.module
(:require [my-project.core :as core]))
Now, when I use 'cider-load-file on core.clj, I have an error due to function of module.clj, and if i start with module.clj, I have a error due to function of core.clj.
Is their a way to fix the issue, or is my code should be refactored ? It seems that I am able to build the jar with lein.
You must refactor to avoid dependency cycles. This is a feature of Clojure, not a requirement added by Cider or waived by Leiningen. "Building a jar" of Clojure stuff just means zipping it up, and thus is not a sign that the stuff is error-free.
I have 2 external Clojure files in my file system.(a.clj and b.clj)
/Users/e/.somedir/a.clj:
(ns a (:require [b]))
(b/printt)
/Users/e/.somedir/b.clj:
(ns b)
(defn printt [] (println "aaaa"))
The thing is I want to be able to load those files to my REPL(preserving dependency order)
If I load a.clj first I get this exception:
(clojure.main/load-script "/Users/e/.somedir/a.clj"):
CompilerException java.io.FileNotFoundException: Could not locate b__init.class or b.clj on classpath., compiling:(/Users/e/.somedir/a.clj:1:1)
If I load b.clj first there is no problem.
So how can I figure this dependency order out and load b.clj first, imagine that this is a complex dependency graph, are there any code examples?
P.S: I don't want to use leiningen or any other build tool(want to do it programmatically). There could be some kinda library/code snippet that shows me files that needed to get loaded in dependency order. How do build tools like leiningen achieve this thing? They do it in some way.
You don't need to load all the files, just the root file of your dependency tree. The other source files are loaded as needed. So if namespace A requires namespace B and namespace B requires namespace C, then you just:
(load "com/example/A.clj")
and B.clj and C.clj are loaded automatically.
Also, since you're not using a build tool, you'll need to be careful about a few things:
1) You need to make sure your source files folder structure mirrors your namespace declarations so an ns of 'com.example.A' should be in a folder structure like src/com/example/A.clj. If you don't Clojure has no way to know where a dependency is located in the file system.
2) A running Clojure REPL is initiated with a specific class path. If the 'src' folder above was not defined on the classpath, Clojure doesn't know about it. So be careful to add that folder to your classpath: java -jar clojure-1.9.0.jar -cp [need to include your src folder here] clojure.main
One last note, running without a build tool like Leiningen means you'll need to be an expert on java class paths and understanding Clojure's dependency model. That's a lot for someone trying to learn Clojure.
You say do not want to use lein or any other build tool, and that's fine. So you'd be better just to organize your code according to Deps & CLI Guide about the latest CLI tools released with Clojure 1.9.
Briefly, in your folder, create another src folder and put all the .clj files there. The system will find them automatically. For example:
└── your-project
├── deps.edn # your dependencies
└── src
└── a.clj
└── b.clj
Then, in the root of your project, just run clj, and the REPL will appear. There, you may require your modules as well.
Take a look at this article, it would really help.
This is easy if you set up your project using lein. Here is an example project fred. To create a simple project, just type:
> lein new app fred
> cd fred
> cp src/fred/core.clj src/fred/second.clj
It now looks like so:
fred
└── src
├── fred
├── core.clj
└── second.clj
with 2 source files core.clj and second.clj. Add your functions:
> cat src/fred/core.clj
(ns fred.core)
(defn aaa [& args]
(println "aaa - enter")
(println "aaa - exit"))
> cat src/fred/second.clj
(ns fred.second
(:require [fred.core :as fc]))
(defn bbb [& args]
(println "bbb - enter")
(fc/aaa)
(println "bbb - exit"))
Then, you can access both using lein repl:
> lein repl
Clojure 1.9.0
fred.core=> (aaa)
aaa - enter
aaa - exit
nil
fred.core=> (require '[fred.second :as fs])
nil
fred.core=> (fs/bbb)
bbb - enter
aaa - enter
aaa - exit
bbb - exit
nil
fred.core=>
You can also use the following variant to reload a namespace and its dependencies:
(require '[fred.second :as fs] :reload-all)
although this is not perfect and can get into a confused state (see How to reload a clojure file in REPL for more details).
I think I found the solution first of all I created dependency graph then I sorted namespaces in topological order so this is the thing I've been looking for a while. Now I can load Clojure files in that order(increasing dependency order).
I have implemented a hyphenation algorithm (at namespace hyphenator-clj.core), defined it as org.clojars.nikonyrh.hyphenator-clj 0.1.0 at defproject and pushed it to Clojars. Uberjar seems to have files like core__init.class, core.clj and core.class.
However when I try to use it as a dependency on an other project I get this error:
$ lein uberjar
Retrieving org/clojars/nikonyrh/hyphenator-clj/org.clojars.nikonyrh.hyphenator-clj/0.1.0/org.clojars.nikonyrh.hyphenator-clj-0.1.0.pom from clojars
Retrieving org/clojars/nikonyrh/hyphenator-clj/org.clojars.nikonyrh.hyphenator-clj/0.1.0/org.clojars.nikonyrh.hyphenator-clj-0.1.0.jar from clojars
Compiling example.core
java.io.FileNotFoundException: Could not locate org/clojars/nikonyrh/hyphenator_clj__init.class or org/clojars/nikonyrh/hyphenator_clj.clj on classpath. Please check that namespaces with dashes use underscores in the Clojure file name., compiling:(core.clj:1:1)
Exception in thread "main" java.io.FileNotFoundException: Could not locate org/clojars/nikonyrh/hyphenator_clj__init.class or org/clojars/nikonyrh/hyphenator_clj.clj on classpath. Please check that namespaces with dashes use underscores in the Clojure file name., compiling:(core.clj:1:1)
at clojure.lang.Compiler$InvokeExpr.eval(Compiler.java:3657)
at clojure.lang.Compiler.compile1(Compiler.java:7474)
at clojure.lang.Compiler.compile1(Compiler.java:7464)
at clojure.lang.Compiler.compile(Compiler.java:7541)
at clojure.lang.RT.compile(RT.java:406)
at clojure.lang.RT.load(RT.java:451)
at clojure.lang.RT.load(RT.java:419)
at clojure.core$load$fn__5677.invoke(core.clj:5893)
...
Must I change my project's folder structure so that it matches the expected org/clojars/nikonyrh/hyphenator_clj__init.class, or can I somehow override the current behavior? If there is a good tutorial about this out there I would be happy to read it.
Basically I would like to get this example project to work. project.clj:
(defproject example "0.0.1-SNAPSHOT"
:description ""
:dependencies [[org.clojure/clojure "1.8.0"]
[org.clojars.nikonyrh.hyphenator-clj "0.1.0"]]
:javac-options ["-target" "1.6" "-source" "1.6" "-Xlint:-options"]
:aot [example.core]
:main example.core)
src/example/core.clj:
(ns example.core
(:require [org.clojars.nikonyrh.hyphenator-clj :as h])
(:gen-class))
(defn -main [& argv] (doseq [arg argv] (println (h/hyphenate arg :hyphen \-))))
I'm suspecting I also have the english.txt in a wrong directory, as it isn't contained in the uberjar but resource files are an other topic.
You would probably be better off not using a hyphen in the namespace hyphenator-clj. Why not just use hyphenator? But if you do I suspect that the name of the directory should have an underscore in it rather than a hyphen, so be: hyphenator_clj.
If fixing that issue doesn't help then another thing to look out for, which I can't see from your question, is where exactly is core.clj in the directory structure, and does the project.clj reflect that? For instance is the path for the namespace hyphenator-clj.core in a src directory off the root of your project? The root of your project being defined as where the project.clj is located.
Something else that would be good to see in the question is whether you can get the program to work just locally, without having packed it up into an uberjar and shipped it to clojars. My guess would be that it does work locally, but it would help for that to be stated.
Okay taking a look at your links now. You might like to read a working project deployed to clojars, that has hypens in its name, for instance here. The first difference you might notice is the project name you use is rather long: org.clojars.nikonyrh.hyphenator-clj. It should just be hyphenator-clj. Also I would recommend having an identifier ending in "-SNAPSHOT" as that project does.
But taking a look at the bigger picture, a great idea you suggested in the comments is to test without Clojars being in the mix at all. To do this use lein install on the library you want to use from another lein project.
Ahaa at least I understand the process a bit better now, basically my require has to match the structure of the used JAR file, which may be very different from the project's name. For example cc.qbits/spandex is actually required as qbits.spandex.
The english.txt dependency was fixed by moving it to resources folder, deploying the new version to Clojars and importing the dependency as it exists in the JAR:
(ns example.core
(:require [hyphenator-clj.core :as h])
(:gen-class))
(defn -main [& argv] (doseq [arg argv] (println (h/hyphenate arg :hyphen \-))))
Where should I use put code files I write myself in a Clojure luminus application? And how can I export a function from it and import it to another file? Say, I've create a file "helper1.clj", how can I access the functions from it in "src/clj/my_app/routes/home.clj"? And where should I put the file "helper1.clj"?
Look at the project.clj file. You will see a line that reads:
:source-paths ["src/clj"]
This means that the src/clj directory will be the root of all namespaces. The namespace is the directory path separated by dots, with the final portion of the namespace being the file name. An example:
File name: my_app/src/clj/dirone/dirtwo/myfile.clj
Namespace in this file: (ns dirone.dirtwo.myfile ...)
With that now established: you should probably put new files in src/clj/my_app for now. The namespace for helper.clj would then look like:
(ns my-app.helper ...)
You can create new directories under src/clj, for example, src/clj/newdir. A file in that directory called anotherfile.clj would have a namespace of:
(ns newdir.anotherfile ...)
Look in your my_app/routes/home.clj file and look at the top, and you will see where :require [my-app.layout :as layout]. You would add the following to reference your function myfunc in your file helper.clj:
;... list of items under :require
[my-app.helper :as h]
;...
(def something (h/myfunc ...))
The error as shown on the Noir error page: java.io.FileNotFoundException: Could not locate boundaries/lat_long__init.class or boundaries/lat_long.clj on class path
The code that requires it:
(ns boundaries.views.boundary
(:use noir.core
hiccup.core
hiccup.page-helpers)
(:require
[boundaries.lat-long :as lat-long]
[noir.response :as resp]))
Why is it looking for lat_long instead of the specified lat-long? boundaries/lat-long.clj exists as well as the corresponding boundaries.lat-long namespace.
the JVM does not allow -s in class names so the Clojure compiler converts them to _s
the problem is most likely with the project.clj dependencies.
When diagnosing this sort of issue:
is the namespace available from the REPL?
does the .class file appear in the lib directory for the project?
re-run lein deps
You need to rename the boundaries/lat-long.clj to boundaries/lat_long.clj.
Note that you don't have to change the namespace name. The clojure convention is to use "-" for functions and namespace names.
From Stuart Sierra response at https://stackoverflow.com/a/4451693/151650: "It's a necessary workaround for Java interoperability."