Make clojure functions available in every namespace during development? - clojure

I have number of useful helper functions that I use at the REPL during Clojure development. This includes some built-in functions like doc and pprint, but also some custom ones of my own from my user.clj. The default clojure experience seems to be:
dev> (doc +)
;; works
dev> (in-ns 'project.core)
project.core> (doc +)
;; what is this "doc" thing you're talking about!?!?
which is pretty irritating (I'm aware that I can refer to clojure.repl/doc here). Is there an easy way to ensure that something is available during development regardless of which namespace I'm currently operating in?

One option is to add a :repl-options to your project map in project.clj:
(defproject myproj "1.0"
:dependencies [[org.clojure/clojure "1.9.0-alpha15"]]
:repl-options { :init-ns myproj.core
:init (require '[clojure.repl :refer :all]) })
...
$ lein repl
myproj.core=> (doc +) ; works

As Alex Gherega mentions, it's probably a bad idea to automatically and indiscriminately import stuff into every namespace. However, you could create a macro (or maybe a function would work?) to help import development-related namespaced when/if they are needed. Add it to your user.clj. Then if you are working in another namespace and decide it would be useful, you can just run (user/import-useful-dev-stuff) (or whatever you decide to call it).
For what it's worth, I pretty much do all my REPL sessions within the user namespace and require all the namespaces I need from there. I use Emacs, and if I need to change something in another namespace, I just change the source, then do C-c C-k (after initiating a cider session) to reload the file. If you don't use Emacs, it's only a little more work to reload from the REPL via require with the :reload option.

Unless you use boot or lein or some other form that would "magically" add this namespace to your REPL development session then I'm afraid you're just have to require it by hand every time.
The thing is namespaces have their well intended role of avoiding name conflicts. If you would have another way of telling a current namespace to use/require another namespace without doing it then you would have a whole lot of other problems.
If you're not using lein/boot you could just do as Alex Miller responded. For a more controlled way of what you need from the clojure.repl or some other ns API just have a require & use declaration in you namespace of interest e.g.:
(ns 'project.core
(:require [clojure.repl :refer [doc]]))

If you get yourself in this situation, do:
(clojure.core/refer-clojure)
to require and load everything from clojure.core.
Or an alternate approach, if project.core exists, is to instead:
(require 'project.core)
(in-ns 'project.core)
Loading the namespace via require will refer clojure.core.
Or if project.core does not exist, do:
(ns project.core)
The ns macro will do both refer-clojure and in-ns.

Related

How do I require clojure.java.io with lein exec?

I am totally new to clojure. I would like to start writing simple scripts, and I came across lein-exec as a means of doing so even if a script contains dependencies. Although I can run an example I found online, I don't know how to require clojure.java.io.
(require 'leiningen.exec)
;places the dependency on the classpath
(leiningen.exec/deps '[[enlive/enlive "1.1.4"]])
(require '[net.cgrand.enlive-html :as html])
How would I require something like clojure.java.io using lein exec?
EDIT: adding more detail
(require 'leiningen.exec)
(leiningen.exec/deps '[[clojure.java.io]])
(require 'clojure.java.io)
(defn Example []
(.exists (clojure.java.io "Example.txt")))
(Example)
gives me
Caused by: java.lang.IllegalArgumentException: Provided artifact is missing a version: [clojure.java.io]
and this
(require 'leiningen.exec)
;(leiningen.exec/deps '[[clojure.java.io]])
(require 'clojure.java.io)
(defn Example []
(.exists (clojure.java.io "Example.txt")))
(Example)
gives me
Caused by: java.lang.ClassNotFoundException: clojure.java.io
Well, personally, I'd recommend using inlein instead of lein-exec for doing scripting with Clojure:
http://inlein.org/
https://github.com/hypirion/inlein
I find it nicer, and it uses standard lein dependency map for defining your dependencies.
Secondly, this: (require 'clojure.java.io) IS the right way to require clojure.java.io. That namespace is included with Clojure itself, so you don't need to declare an additional dependency on any other library to use it.
Your problem is that you are not using it correctly:
(.exists (clojure.java.io "Example.txt"))
In the above code, you are calling clojure.java.io as if it was a function, but it is not a function, it is a namespace. You need to choose a function inside of it to call, such as the file function. If this was java, you could kinda think of the namespace as the class, and the function as a method on the class. If you do:
(.exists (clojure.java.io/file "Example.txt"))
It should work now. Notice how in Clojure, the syntax is: namespace/function. This is different the some other languages like Java or Python, where you would have: some.location.class.method instead, basically the function is also separated by a .. This is not the case in Clojure, in Clojure, the function part is separated by a /.

Running seesaw and overtone libraries in clojure

I want to use the overtone and seesaw namespaces in one project. However when i load them there seems to be a shared function named (select) which exists in both seesaw.core and overtone.core ((seesaw.core/select) (overtone.core/select)), why i can't load both of the namespaces in the project. How could i come up with this? Will using refer with the :exclude keyword an option?
While many tutorials and examples use the use function or the :use clause in the ns form, in real code it is better to never do this. The preferable form is as follows:
(ns foo.bar
(:require [a.something :as some]
[b.another :as a]))
(some/f)
(a/f)
The functions are fully distinct and unambiguous, and also this makes the code easier to read and refactor - you have a clear indication of where the definitions you are using come from.

Import Record Type in Clojure/ClojureScript

Is there any way to import a record type, that works in Clojure as well as ClojureScript?
As far as I can tell it's (ns x (:import y [A B])) for Clojure, (ns x (:require y :refer [A B])) for ClojureScript, and each is invalid for the respective other.
Ignoring the specifics on the syntax of requiring records, there are two main ways to write ns declarations (or any platform specific code) for multiple Clojure variants while sharing the majority of your code.
CLJX is a Clojure preprocessor that runs before the Clojure compiler. You write platform specific code prefixed with #+clj or #+cljs in a .cljx file. It can run on pretty much any Clojure code, and will spit out multiple platform specific files which the respective Clojure Compilers can handle.
Reader Conditionals are a feature in Clojure 1.7 and are available in recent releases of ClojureScript. This is similar in spirit to cljx, but is integrated into the Clojure Compiler. You write code with reader conditionals like #?(:clj 1 :cljs 2) in files with a .cljc extension.
Now back to your specific question, you can achieve this with Reader Conditionals like so:
(ns myapp.music-store
(:require #?(:clj [myapp.cool-music]
:cljs [myapp.cool-music :refer [Vinyl]]))
#?(:clj
(:import [myapp.cool_music Vinyl])))
I wrote a longer blog post about this too: Requiring records in Clojure and ClojureScript

Trying to understand implicit Leiningen source path/namespace set up assumptions

(Sorry this is so long. It's long to rule out misunderstandings, not because I want you to figure out what my question should be.)
I understand the basics of Clojure namespaces, and that the namespaces listed in my ns statements at the beginnings of files have to match locations of files in a directory hierarchy. I have figured out part of what Leiningen is doing automatically to set up search load, and part of what it is loading automatically, but ... it's still driving me crazy. The problem is that there are things that Leiningen seems to set up implicitly, that are also not well documented in the obvious places like the Leiningen tutorial and the sample project file. (Maybe the information is there, but I haven't found it/interpreted it.)
I've got things set up so that when I do lein repl, the main source files are loaded (popco.clj and acme.clj below), but loading other files causes trouble. I want to make the MWE as minimal possible, and the question short, but I want to make it clear that I am not asking simpler questions that have been answered already (e.g. this one).
Here's where source files are, with ns statements from the same files listed over on the right:
src/popco/sims/sim1/sim1propns.clj (ns popco.sims.sim1.sim1propns)
src/utils/general.clj (ns utils.general)
src/popco/core/acme.clj (ns popco.core.acme)
src/popco/core/popco.clj (ns popco.core.popco
[:use popco.core.acme]
[:import [popco.core.acme Propn Obj]]
(:gen-class)) ; not sure what this does yet
Here's the project.clj file:
(defproject popco-x "0.0.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.5.1"]]
:main popco.core.popco
:profiles {:dev {:dependencies []
:source-paths ["src"] }})
When I run lein repl, I see that I'm in the popco.core.popco namespace:
popco.core.popco=>
and I find that both functions and record types defined in acme.clj are available. I have learned (by trial and error) that ":main popco.core.popco" in project.clj is causing popco.clj to run, and that results in the the REPL being left in the popco.core.popco namespace. So far, so good.
Here are my questions:
What if I want to load src/utils/general.clj, or src/popco/sims/sim1/sim1propns.clj ? I can load them with load-file, but I'd like to use load in the REPL, and more importantly, I'd like to be able to require or use these source files from other source files. How can I reference the functions in general.clj from inside acme.clj, for example? I think the answer might be to add entries to the sequence after :source-paths in project.clj, but I'm confused about what should go there.
Feel free to recommend anything. Other directory structures, radical changes to project.clj, whatever.
Everything about your project structure and project.clj looks entirely normal.
What if I want to load src/utils/general.clj:
This is almost always done through a require or use expression. While it is possible to load a file with load-file this requires you to specify the path (relative to where you started the JVM) to the file. load loads it relative to the class-path though in practice these are almost never used when the files being loaded are part of the project. In that case you can simply require them.
I'd like to be able to require or use these source files from other source files:
The expected way of doing this is to put a (:require [popco.core.acme :as acme]) statement in the ns form at the top of the namespace that wants to use functions from that namespace.
How can I reference the functions in general.clj from inside acme.clj:
(ns popco.core.acme
(:require [utils.general :refer [function1 function2] :as general))
I think the answer might be to add entries to the sequence after :source-paths in project.clj:
You will most likely never need to put anything there. require and use are the appropriate tool for this. They will already be able to find all the files under /src/ because those files will be in the classpath when the leiningen starts java. You can see the class path used with the lein classpath function.
ps: You can also call require and use as functions (form the REPL for instance), though doing this in the ns form is generally preferred.

Clojure warning: "resultset-seq already exists in clojure.core"

I'm new to Clojure and building a web app using the Noir framework (very similar to Compojure, in fact I think it's Compojure with a different request handler layer). I'm getting a warning when I import the JDBC library:
WARNING: resultset-seq already refers to: #'clojure.core/resultset-seq in namespace: webapp.models.database, being replaced by: #'clojure.java.jdbc/resultset-seq
Do I have to live with this warning or is there a way around it? I'm importing the JDBC library using:
(use 'clojure.java.jdbc)
You can avoid the problem by specifying the exact bindings to be imported:
(use '[clojure.java.jdbc :only [insert-values transaction]])
(transaction
(insert-values ...))
Another option is to :exclude the offending binding:
(use '[clojure.java.jdbc :exclude [resultset-seq]])
(transaction
(insert-values ...))
You can also just use require instead:
(require '[clojure.java.jdbc :as db])
(db/transaction
(db/insert-values ...))
With regard to forward compatibility, require is arguably safest. Using :only is just slightly less clean but still a pretty good approach (and easy to fix when it breaks). Excluding the currently offending bindings is probably the least future-proof way of fixing the problem since other conflicting bindings can appear at any time and tracking down what is imported from where can be tricky.
There are lots of options. What this warning means is, that you are replacing an already defined symbol with a definition from different package. In this case, it looks like this is a variable that you've defined, right? If so the easiest solution might be to just rename it in your code.
Or if you don't need the resultset-seq from clojure.java.jdbc package you can exclude it:
(use '[clojure.java.jdbc :exclude (resultset-seq)])
or better yet,
(use '[clojure.java.jdbc :only (f1 f2 f3)])
where f1, f2, f3 are the things you're actually need.
(use '[clojure.java.jdbc :as jdbc])
and then use jdbc/resultset-seq
Or you can just:
(require 'clojure.java.jdbc)
and then use clojure.java.jdbc/reusltset-seq
In addition to the other excellent answers, if you want the jdbc resultset-seq instead of the core one, you can exclude the latter from being brought into the current ns:
(ns foo
(:refer-clojure :exclude [resultset-seq])
(:use clojure.java.jdbc))