load a new dependency in slime? - clojure

I am using emacs and swank-clojure. How do I resolve the below scenario -
I have added a new dependency to project.clj.
I run lein deps in a shell to get the new dep.
I have an existing slime session that is open and want to use a function from the new dep.
How do I get the existing slime session to load the new dependency ?
Thanks,
Murtaza

You should have a look at pomegranate which is designed to provide similar if not identical capabilities as the one you describe.
As pointed out by #gergek in the comments, leiningen2 ships with pomegranate, so that if you're on lein2 you have to just fire something like the following in the slime REPL:
(require '[cemerick.pomegranate :as p])
(p/add-dependencies :coordinates '[[org.clojure/core.logic "0.7.5"]])
Have a look at add-dependencies docs for more info on how to use it.

Related

clojure.tools/namespace refresh fails with "No namespace: foo"

I'm using tools.namespace to provide smart reloading of namespaces on the REPL. However, when calling refresh or refresh-all, it throws an error.
user=> (require '[clojure.tools.namespace.repl :as tn])
user=> (tn/refresh)
:reloading (ep31.common ep31.routes ep31.config ep31.application user ep31.common-test ep31.example-test)
:error-while-loading user
java.lang.Exception: No namespace: ep31.config, compiling:(user.clj:1:1)
And it seems to end up in this weird state where (require ep31.config) works without an error, but afterwards the namespace isn't actually defined.
I kind of figured this out, this seems to be a combination of circumstances
there were AOT compiled classes left in target/classes from doing lein uberjar previously
tools.namespace doesn't function correctly when loaded namespaces are AOT compiled
target/classes is by default on the classpath
So long story short, if you did a jar/uberjar build before, then remove target/ and things should start working again.
The question I haven't been able to solve yet is why target/classes is on the classpath to begin with. I'm suspecting it's being added by Leiningen, but haven't found yet where or why it's happening.
I learned this the hard way, documentation for :target-path says (https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L309-L313):
;; All generated files will be placed in :target-path. In order to avoid
;; cross-profile contamination (for instance, uberjar classes interfering
;; with development), it's recommended to include %s in in your custom
;; :target-path, which will splice in names of the currently active profiles.
:target-path "target/%s/"
I guess there has to be legacy reasons that :target-path "target/%s/" isn't the default.

How do I depend on every clojure contrib library?

I used to like to include all of clojure.contrib, and require all the libraries. This makes find-doc useful as a discovery tool.
Nowadays (clojure 1.4) clojure.contrib is split into many sub-libraries. And that rather spoils my scheme, and it also means that I am constantly having to restart the JVM every time I need a new library.
So I'm busy constructing a project.clj file with many lines:
[org.clojure/algo.generic "0.0.6"]
....
[org.clojure/data.xml "0.0.4"]
....
So that I can get leiningen to put every clojure contrib library on the classpath, whether I need them or not.
And I reckon that this is going to be a spectacular pain in the neck, what with the version numbers, and all.
And I wonder if anyone has a better way to do the same thing?
EDIT: Thinking about it, if there's a web page somewhere that has a list of library names and current versions, I can turn that into a project file fairly easily.
You could use pomegranate if you just want to run it in the REPL (which seems like it would be the only appropriate use case, right?). You can have it look up the latest versions using the Maven Central API. I think this is better than maintaining some sort of dependencies project, generated or otherwise.
(require '[cemerick.pomegranate :refer [add-dependencies]])
(add-dependencies
:coordinates '[[clj-http "0.5.8"]]
:repositories {"clojars" "http://clojars.org/repo"})
(require '[clj-http.client :as client])
;; contrib project names from https://github.com/clojure
(def contrib ["tools.nrepl" "tools.trace" "tools.namespace" "tools.macro"
"test.generative" "math.numeric-tower" "core.match" "core.logic"
"data.priority-map" "core.contracts" "tools.cli" "java.jmx"
"java.jdbc" "java.classpath" "data.xml" "data.json" "core.unify"
"core.incubator" "core.cache" "algo.monads" "data.generators"
"core.memoize" "math.combinatorics" "java.data" "tools.logging"
"data.zip" "data.csv" "algo.generic" "data.codec"
"data.finger-tree"])
(defn add-contrib-dependencies
"look up the latest version of every contrib project in maven central,
and add them as dependencies using pomegranate."
[project-names]
(add-dependencies
:coordinates
(map (juxt
(comp symbol (partial format "org.clojure/%s"))
(fn [proj]
(Thread/sleep 100)
(-> "http://search.maven.org/solrsearch/select?q=%s&rows=1&wt=json"
(format proj)
(client/get {:as :json})
:body :response :docs first :latestVersion)))
project-names)))
Now you can just invoke this function on the list of project names:
user=> (add-contrib-dependencies contrib)
{[org.clojure/data.zip "0.1.1"] nil,
[org.clojure/java.classpath "0.2.0"] nil,
[org.clojure/core.cache "0.6.2"] nil, ...}
UPDATE: as suggested earlier, I had made this answer into a library. It can be used either as nREPL middleware or invoked manually from a running REPL session. The code can be found at https://github.com/rplevy/contrib-repl, where usage instructions can also be found.
I feel your pain. It should be helpful http://dev.clojure.org/display/community/Where+Did+Clojure.Contrib+Go

FTP with Clojure

Are there any libraries to perform FTP transfer with clojure, idiomatic to clojure, or is it necessary to use a java library such as apache commons?
Thanks
It is not necessary to use java library and you can roll complete FTP implementation in Clojure but that would be like re-inventing the wheel and not a feasible thing to do. What you can do is probably write a more functional wrapper over the Java library and then use that wrapper in your clojure code so that everything seems seamless and that't how many of the existing Java libraries are being used in Clojure.
You can use https://github.com/miner/clj-ftp either by invoking few convenience functions or by opening a client and invoking multiple commands with it.
The full API is documented in GitHub at https://github.com/miner/clj-ftp/blob/master/src/miner/ftp.clj .
Contents of project.clj
(defproject my-sweet-project "0.5.0"
:dependencies [[com.velisco/clj-ftp "0.3.0"]
; Other deps
]
; ...
)
Invoking a single FTP command
This will open new FTP connection for each command so it should be used for invoking a single command only. See the full API for complete list of these convenience functions.
(ns my-sweet-name.space
(:require [miner.ftp :as ftp]))
(defn list-files-from-ftp-server []
"Here we list contents of a directory with a convenience function"
(let [ftp-url "ftp://username:password#my.ftp.server.host:port/path/to/stuff"]
(ftp/list-files ftp-url)))
Invoking multiple commands with same connection
This will open FTP connection and invoke arbitrary amount of commands with it. This should be used when multiple commands should be invoked. The FTP connection will be automatically closed. Again check the full API for complete list of functions.
(ns my-sweet-name.space
(:require [miner.ftp :as ftp]))
(defn list-and-download-files []
"Here we list and download contents of a directory"
(let [ftp-url "ftp://username:password#my.ftp.server.host:port/path/to/stuff"]
(ftp/with-ftp [ftp-client ftp-url]
; client-file-names is used to list contents of the ftp-url
; client-get is used to download a file
(doseq [file-name (ftp/client-file-names ftp-client)]
(let [local-file-name (str "/download-path/" file-name)]
(ftp/client-get ftp-client file-name local-file-name))))))
https://github.com/miner/clj-ftp is a wrapper over Apache Commons Net.

Code run in REPL but not if saved to a file

I'm trying to create a text based Clojure game (inspired by Land of Lisp).
(def *nodes* {:living-room "you are in the living-room. a wizard is snoring loudly on the couch."
:garden "you are in a beautiful garden. there is a well in front of you."
:attic "you are in the attic. there is a giant welding torch in the corner."})
(defn describe-location [location nodes]
(nodes location))
The code is running in the REPL but if I saved the code to a file and trying to run:
(describe-location :attic *nodes*)
I got:
Exception in thread "main" java.lang.IllegalArgumentException: Wrong
number of args (1) passed to: user$describe-location (wizard-game.clj:
0)
What I'm doing wrong?
Here is the file: http://dl.dropbox.com/u/3630641/wizard-game.clj
You have too many parentheses. Instead of (describe-location(:garden *nodes*)), you want (describe-location :garden *nodes*).
Remember that the name of the function goes after the open paren, not before: you were calling (:garden *nodes*) and then calling describe-location on the result, which failed because describe-location wants two arguments, not one.
one potential problem is that the version of the function that is loaded into the repl in the 'user' name space may not be the one you expect, so you may want to (load "wizard-game.clj") into a fresh REPL. though many people are using leiningen for this these days, except for the good number of people using maven directly.
first give your're game a namespace
(ns com.me.myGame
....)
then you can load it into the repl by running
(use 'com.me.myGame)
and call the functions by either their name-space-qualified names
(com.me.myGame/describe-location :attic)
or from the repl switch into that namespace:
(in-ns 'com.me.myGame)
(describe-location :attic)
or you can use leiningen to create your project and name-space automatically.
leiningen is worth it in this case because it just took me longer to write this sentence than to make a project with lein. There are a lot of good tutorials for leiningen.
lein new wizard-game
and then edit src/wizard-game/core.clj. this will let you add dependencies later with out fuss if when the project grows to world-famous-success

Enclojure REPL can't find dependent clj file on Load

I have a problem with the Enclojure REPL and using clojure modules from it. The Load/Change REPL to file/ns works fine with an isolated clojure file, but breaks with a file which has references to another clojure file which I try to use from my project.
Here are the exact steps:
Create a new project.
Create a clojure module foobar.clj (namespace com.acme.foobar)
Define a function which returns a value in foobar.clj:
(ns com.acme.foobar
(:use com.acme.othermodule))
(defn myfunc1 []
"a")
Open a Netbeans IDE REPL
From foobar.clj's context menu select:
Change REPL to file/ns
Load
From REPL call the (myfunc1) function. This works just fine:
com.acme.foobar=> (myfunc1)
"a"
The problems start when when I try to refer to other files from foobar. Here's what I do:
Create a new clojure module othermodule.clj
(ns com.acme.othermodule)
(defn fromothermodule []
"b")
Now try to call this from foobar.clj:
(defn myfunc2 []
(fromothermodule))
From othermodule.clj's context menu I select:
Change REPL to file/ns
Load
To make the REPL realize that there is new module it should be able to run.
I do same things things to foobar.clj which now refers to othermodule.clj, but I get:
CompilerException java.io.FileNotFoundException: Could not locate com/acme/othermodule__init.class or com/acme/othermodule.clj on classpath: (NO_SOURCE_FILE:50)
com.acme.foobar=>
This error message comes from both "Change REPL to file/ns" and "Load"
What am I missing? Should I do some other tricks to make this happen? Even the desperate measure of Run->Clean and Build the main project doesn't help (that would of course make the REPL business pretty painful anyway).
I am using NetBeans 6.7.1 and enclojure-plugin-2009-11-3.nbm.
Got the right solution from Eric Thorsen in the google group:
There are three ways to create the REPL from window-menu. Don't use any of those, instead right
click on the Project and "Start Project REPL". Now the paths are set up accordingly.
My first recommendation is to move from NetBeans/Enclojure to IDEA/La Clojure. JetBrains recently created an open source version of their IDE, and the Clojure plugin works fine in it. Since discovering this, I ditched NetBeans and Enclojure. I find La Clojure a pleasure to work in, but of course your mileage may vary.
Back from when I did this in NetBeans, I seem to remember Enclojure source code resides in a subdirectory called "lib". I think I solved a similar problem by fiddling with directory prefixes on the name of the file to load. Probably something like "../lib/YourName". I managed this by trial and error, so I can't relate the exact rules and syntax.
Two things that might help:
You can run something like (println (System/getProperty "java.user.dir")) to find out where Clojure thinks it's executing from.
You could start, as I did, with using an absolute path until you find your way to the correct directory name. Something like "/home/carl/NetbeansProjects/MyProject/lib/myfile.clj" .