Custom files in luminus - clojure

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 ...))

Related

Why am I unable to load files in Clojure?

I have just started learning clojure, but have a hard time understanding why my file structure is erroneous. In the main file(main.clj),
I have just this:
(ns example.core
(:gen-class)
(:load "declare"))
...some code...
and in 'declare.clj', which is in the exact same classpath "project/src", I have this:
(in-ns 'example.core)
...some code...'
From what I understand I should be hitting the right syntax, but I only receive
Could not locate
clojurepractice2/src/clojurepractice2/declarations__init.class or
clojurepractice2/src/clojurepractice2/declarations.clj on classpath.
from REPL. I am using lein to code, which I know is supposed to automatically set the classpath. Is there something I am missing?
I have tried using load-file With the same results.
The main.clj should have namespace example.main. Or rename it to core.clj. This is definitely an issue with file name and namespace mismatch.
Because the file name should be same as the namespace name.
If your file is in src/example/main.clj then the namespace should be example.main.
The usage is
(ns example.main
(:gen-class)
(:load "declare"))
Is the file path as src/example/main.clj ? Is the main inside the example folder in src?

Clojure and leiningen: declare and require namespace

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)

Naming differences between project dependencies and :require

When I look at something like, say, the clojure.data.json source code I can see a namespace looking, for example, like this:
(ns clojure.data.json...)
So when I want to :require that in my .clj Clojure files, I simply do something like this:
(ns so.example
(:require [clojure.data.json :as json])
...
However in the dependencies in my .clj I have:
:dependencies [[org.clojure/data.json "0.2.4"]
So the clojure.data.json "became" org.clojure/data.json.
Now for, say, server.socket I have in my dependencies:
[server-socket "1.0.0"]
So this time no ".org" added, no slash, but the dot became a dash.
What's the relation between :require in Clojure source files and :dependencies in project.clj? Is there any "logic"?
How can I find what's the correct line to put in the dependencies?
The dependency vectors in project.clj are the maven artifact coordinates to resolve the dependency by finding the appropriate jar. Leiningen will attempt to find the apropriate jars and add them to your classpath so that namespace definitions and other resources can be loaded from inside their archive contents at runtime. The require statement in your code specifies a resource to look for in the class path. For example if you require clojure.data.json, Clojure will look for a resource with the path clojure/data/json.clj somewhere in your classpath, and attempt to load the definition for the namespace clojure.data.json from that resource.
There is no relationship. Namespace is something defined in the source code file. A dependency is based on a project name and is decided by the author(s) when they publish it. You'll almost always find the proper dependency information on the project github site or at Clojars, or in some cases, maven.

Locating Clojure Browser Dom

I am using the following namespace for a graphics demo
(ns foo.core
(:use [clojure.browser.dom :only [get-element]]))
However, I return a File not found exception for clojure browser dom in the classpath.
Clojurescript has been pulled, and is contained within the file I cd into. But is not contained in the file I am trying to load, after having accessed the REPL.
Is clojure.browser.dom out of date? Or, am I missing something within the implementation?
Edit
I have not included the dependency for this file.
That namespace is correct:
https://github.com/clojure/clojurescript/blob/master/src/cljs/clojure/browser/dom.cljs
Maybe the problem is the ns form? Try
(ns foo.core
(:require [clojure.browser.dom :refer [get-element]]))
Also, just in case, be sure to name your file .cljs and restart the cljsbuild compiler, just in case.

Clojure namespacing converting - to _

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."