Load clj files through a leinigen-based repl - clojure

I'm trying to run snake.clj from the Programming Clojure (3rd ed) book examples. Said file starts with this declaration:
(ns examples.snake
(:import (java.awt Color Dimension)
(javax.swing JPanel JFrame Timer JOptionPane)
(java.awt.event ActionListener KeyListener))
(:require [examples.import-static :refer :all]))
(import-static java.awt.event.KeyEvent VK_LEFT VK_RIGHT VK_UP VK_DOWN)
; actual program omitted, see above link
Because I'm trying to run this on Windows, and the Clojure CLI Getting Started (recommended by the book) isn't yet available on Windows, I'm using leinigen instead. I've used these instructions to run:
lein repl from the examples folder containing my snake.clj file
=> (load-file "snake.clj")
But this gives me an error:
CompilerException java.io.FileNotFoundException: Could not locate examples/import_static__init.class or examples/import_static.clj on class path...
Somehow my setup with a repl through leinigen fails to let me use import-static like that.
As a workaround, I've used WSL Ubuntu to install the Clojure CLI and run it in the root of the book's source code folder, loading the snake file directly using the suggested code in the book ((require '[examples.snake :refer :all])). That loads just fine, I can even run (game) from the loaded file, but of course that crashes because WSL Ubuntu has no GUI options (it crashes on an "No X11 DISPLAY..." error).
I would assume that the leinigen-based setup I used failed because I had to do (load-file "import_static.clj") first. In fact, doing so is a fine workaround because then it all works (after also doing (use examples.snake)), but this doesn't scale very well for multiple/recursive imports.
What is the proper way to use leinigen (on Windows) to run such scripts? Should I've created a leinigen project file? Or is there a repl-trick to do this?

This isn't a direct answer to your question, but it'll help you get up and running.
The problem is that the files aren't on the class path because the author seems have decided to neglect using projects altogether, so leiningen can't help you. The/A solution is to create a new project, and stick everything in there.
How to get it working:
Go to a directory, start up a command prompt there, and run lein new snake. This will create a "snake" folder containing the barebones structure of a project, complete with a "project.clj".
From the files you downloaded, copy the entire "src" folder (that contains the examples folder), and paste it into the new "snake" folder so it overwrites the generated "src". You should now have a path "snake/src/examples/".
Now that "snake/src" is on the class path, it can be referenced as expected. Go to the root "snake" folder, start up a command prompt, and run
lein repl
(require '[examples.snake :as s])
(s/game)
The game window should pop up as expected.

Related

Can I start Gorilla REPL from an uberjar?

I play with this great Gorilla REPL powered project ( https://bitbucket.org/probprog/anglican-examples/ to be specific), and want to use it under certain restricted circumstances.
Is there a way to produce an uberjar that can be started using only a JVM?
Well, I know how to create an uberjar for this project, but can I start a Gorilla REPL from it? If not what do I have to add and how do I start it?
EDITED Note on Juraj's answer:
I added a start file src/gorillaproxy/gorillaproxy.clj with the following content:
(ns gorillaproxy.gorillaproxy
(:use [gorilla-repl.core :only [run-gorilla-server]])
(:gen-class))
(defn -main
[& args]
(run-gorilla-server {:port 8990}))
Then I added [gorilla-repl "0.4.0"] to the dependency list (in project.clj), and the line
:main gorillaproxy.gorillaproxy
In that way the uberjar started the Gorilla REPL, and when I put the worksheets (and data, resources, .. if needed) into the same directory, everything worked fine.
Gorilla is typically run via the lein-gorilla plugin and thus isn't a part of an uberjar.
If you really want to create a bundle containing gorilla repl dependencies, then you need to add it this capability manually to your project.
The question is why would you want to do that.
Do you want to distribute these samples to somebody else? If that's the case, you'll still need to have all those worksheets in the current directory from where your uberjar is run because that's how gorilla repl discovers worksheets.
You can look at lein-gorilla source code to see how gorilla repl can be started.
I'd then at the same code to your project (create new src/core.clj file or whatever) and configure it in your project.clj as :main.
You'll also need to add gorilla-repl as a dependency to your project.clj
Notice however, that you'll need to run that uberjar from a directory where your anglican worksheets are (or a parent directory of such a directory).

How do I use the Clojure `use` function in leiningen?

I am very new to both Clojure and Leiningen. I have installed Clojure on Windows at C:\clojure-1.5.1 and leiningen-win-installer beta1 at C:\.lein\bin.
Now I am trying the example from Eric Rochester's book. I have included dependent libraries for Incanter in project.clj and also using dep.
How do I use the command (use 'incanter.core)? I am getting 'use' is not recognized as an internal or external command. In addition, how do I use lein commands at user=>?
Edit - I forgot "lein deps" until I saw Mars's answer
Before you start lein repl, you have to make the project (with "lein new getting-data" or whatever is in the book).
That makes a new directory, and in that directory you find and edit "project.clj" to include the dependencies (as shown in book).
cd into the directory that project.clj is in and run "lein deps" from the dos/powershell prompt.
THEN when you run lein repl, from within that same directory, at the user=> prompt, do
(use 'incanter.core)
and it will come back with "nil" and you'll be running. You might want to first run some examples from the leiningen page to get more of a feel for lein. You always type clojure commands at the "user=>" prompt, not at the "c:....>" prompt.
There's a bit of subtlety in Leiningen project.clj's. I haven't found an easy introduction. Levin Magruder's advice will no doubt get you started. The basic idea is that once the project file is set up correctly, lein deps will go out and find the libraries you need, and put them in a place where lein repl can find them. Then use will work for the libraries that have been downloaded. For more info, study of the detailed comments project.clj sample file may be helpful. (Not part of the answer to this question, but if you're having problems with use, you're likely to get tripped up by ns and filenames soon (I was): I recommend Colin Jones' introduction to ns and its options.)

cannot load a new clojure library

I'm trying out clojure on my second day and I don't understand almost anything yet. I am working with the Programming Clojure 2nd ed. and I am stuck with libraries.
I have Leiningen and have the REPL running. The book first tells the reader to run a simple
(require 'clojure.java.io)
which works just fine (I get a nil). Then it wants to load a file called introduction.clj by running another simple
(require 'examples.introduction)
where I get an error message
FileNotFoundException Could not locate clojure/java/introduction__init.class
or clojure/java/introduction.clj on classpath: clojure.lang.RT.load (RT.java:432)
I downloaded the introduction.clj file and looked where should I place it. The error and the book says the command will search in my classpath, but I have no idea where or what that is (after 1h of searching and reading I still don't get it, sorry). I ran a few commands and I had many classpaths listed (from which none contain a clojure/java/io.clj).
So I tried another approach - find the io.clj file on my disk and simply copy the file there and run it with a command
(require 'clojure.java.introduction)
This doesn't seem to work either. By the way, the io.clj file I found was in "C:\Program Files\clojure\src\clj\clojure\java". I tried running several other .clj files from the java folder as well from the clojure folder, like javadoc.clj or inspector.clj and all seem to work just fine with the above mentioned command. Only the new file doesn't seem to load this way.
Any help appreciated :)
Clojure runs on the Java Virtual Machine, so you will need to learn a bit about PATH and CLASSPATH concepts:
See: http://docs.oracle.com/javase/tutorial/essential/environment/paths.html
Regarding the error message, the Clojure runtime is expecting to find introduction.clj in the directory clojure\java\example\introduction.clj (not where it really should be - see below).
The convention for Clojure namespaces is that the last component is the file name, while any previous components are parent directories. So
clojure.java.introduction
would have to be in the directory (relative to your source "root" or classpath)
clojure\java\introduction.clj
(The lein REPL automatically adds your source root to the classpath).
Another concept you need to understand is where the "root" of your source code is located. For Leiningen (the build tool you are using) the default is either "src" or "src/main/clojure" - as documented in the Leiningen sample project file on GitHub).
Finally, if you get really stuck, it seems the complete project for the book is available on GitHub.
Looking at the project, I see that you should actually be placing the file under src\examples\introduction.clj
Are you reading the book "Programming Clojure"?
I have encountered the same problem. It ban be sovled as follows:
If you start clojure by java:
I work in windows, the clojure.jar is placed in D:\backup\clojure-1.5.1, and the source code of the book "Programming Clojure" is placed in D:\study\clojure\shcloj-code\code. You should first delete the user.clj file in folder D:\study\clojure\shcloj-code\code.
java -cp d:\backup\clojure-1.5.1\clojure-1.5.1.jar;d:\study\clojure\shcloj-code\code clojure.main -r
If you work in linux, replace the ";" with ":"
If you start clojure by lein
You should first cd to the D:\study\clojure\shcloj-code\code folder, and then
lein repl
You should also delete the user.clj file in folder D:\study\clojure\shcloj-code\code.

Using lwjgl in Leiningen/Clojure

Solution
(1) (println (. System getProperty "java.library.path"))
This gives me a list of places java looks for native extensions.
Then, I took the lwjgl native extensions, and put them there.
Things that didn't work for me (probably because I used them incorrectly)
(*) setting :native-path
(*) setting :native-dependencies
Problem
My setup:
(lein deps; echo "====="; cat project.clj; echo "====="; cat src/main.clj; echo "====="; lein repl) &> log
contents of "log"
Copying 10 files to /Volumes/ramdisk/fail/lib
=====
(defproject
mincase "0.0.1"
:dependencies [[org.clojure/clojure "1.4.0"]
[org.lwjgl.lwjgl/lwjgl "2.8.2"] ]
:repositories {"local" "/Users/x/z/maven_repo"}
:jvm-opts ["-Xms4g" "-Xmx4g"]
:repl-init main
)
=====
(ns main
(:import org.lwjgl.opengl.Display))
=====
REPL started; server listening on localhost port 31235
UnsatisfiedLinkError no lwjgl in java.library.path java.lang.ClassLoader.loadLibrary (ClassLoader.java:1860)
clojure.core=>
Note -- I had already done a "lein deps", so the lwjgl library has been pulled into maven. What I don't understand are:
(*) how do I get access to lwjgl from Clojure?
(*) more importantly, how do I debug which step this whole thing has gone wrong at?
$ find lib
lib
lib/clojure-1.4.0.jar
lib/jinput-2.0.5.jar
lib/jinput-platform-2.0.5-natives-linux.jar
lib/jinput-platform-2.0.5-natives-osx.jar
lib/jinput-platform-2.0.5-natives-windows.jar
lib/jutils-1.0.0.jar
lib/lwjgl-2.8.2.jar
lib/lwjgl-platform-2.8.2-natives-linux.jar
lib/lwjgl-platform-2.8.2-natives-osx.jar
lib/lwjgl-platform-2.8.2-natives-windows.jar
So it appears that lwjgl has been pulled in.
What are the steps I should try to figure out which step I went wrong on?
Thanks!
Dropping this note here since google found this post for my similar question.
The Leiningen folks have now addressed this: https://github.com/technomancy/leiningen/issues/898
If you get version 2.1.0 or later, it has the fix. See the bug for details.
UPDATE: (Aug 2013)
I have a project on github I use for experimentation with lwjgl here: https://github.com/rogerallen/hello_lwjgl
I'm also using LWJGL in my shadertone project here: https://github.com/overtone/shadertone
Because Shadertone is a library, I found I needed to package up the natives myself to get it to install reasonably for projects that depend on shadertone.
If anyone has some pull with the LWJGL folks, it sure would be nice if they just put natives into appropriate subdirectories as lein expects in their clojars releases.
Looks like a problem with your LD_LIBRARY_PATH. Are you including the correct .dll or .so files?
You probably need to add something like :native-dependencies [[lwjgl "2.8.2"]] to your project.clj.
Alternatively, you could try setting the right value from your shell:
export LD_LIBRARY_PATH=/home/username/lwjgl-2.8.2/native/linux/
It's a bit confusing why Display is refusing to import, though other classes in the same jar file import properly
(import '[org.lwjgl.opengl Util WindowsAWTGLCanvasPeerInfo])
I suspect that this jar file is broken, perhaps you could try a different version.
I tried debuggin this by running
cd lib
jar xf lwjgl-2.8.2.jar
cd org/lwjgl/opengl/
and then trying to load various classes i see there.
lein swank also does tab completion which can help in exploring classes without extracting them from the shell.
Ran into this today, solved it a bit differently by adding the native directory to :jvm-opts in project.clj:
(defproject projectname "0.0.1-SNAPSHOT"
:description "my project"
:jvm-opts ["-Djava.library.path=native/linux"]
:dependencies [[org.clojure/clojure "1.4.0"]])
I copied the jar files from the latest lwjgl release into lib and copied the native directory into the project root. Seems to work so far:
user=> (import org.lwjgl.opengl.Display)
org.lwjgl.opengl.Display
But I am only just getting started. Anyway, hope this helps someone else :)

How to add classpath with emacs slime/conjure?

I setup emacs slime/clojure as written here.
When I run (doseq [p (.getURLs (java.lang.ClassLoader/getSystemClassLoader))] (println (.getPath p))) to get classpath, I get the following.
/Users/smcho/.swank-clojure/clojure-1.1.0-master-20091202.150145-1.jar
/Users/smcho/.swank-clojure/clojure-contrib-1.1.0-master-20091212.205045-1.jar
/Users/smcho/.swank-clojure/swank-clojure-1.1.0.jar
How can I add classpath for emacs/slime for clojure?
The procedure differs depending on whether you are using slime-connect to start slime (by connect to a remote swank server, created with lein swank, for example) or you are starting slime using M-X slime.
If you're using slime-connect, you'll need to modify the classpath of the java process that is running the swank server. If you're starting the swank server using lein swank, simply add the jars you want to be part of your classpath to the project's lib directory.
On the other hand, if you're starting slime using M-X slime, the following elisp code will do the magic for you (just place it in your ~/.emacs file).
(eval-after-load "swank-clojure"
'(progn
(add-to-list 'swank-clojure-classpath
"/Users/smcho/.clojure/")
(add-to-list 'swank-clojure-classpath
"/Users/smcho/.clojure/blah.jar")))
This will add /Users/smcho/.clojure/ and /Users/smcho/.clojure/blah.jar to the classpath. (Please note that you'll either need to restart emacs or reload the .emacs file: type M-X load-library and then type .emacs on the next prompt.)
I believe the advised way to fire up a clojure reple nowadays is to use lein swank, and use \M-x slime-connect. See http://github.com/technomancy/leiningen/ for a detailed description of this tool.
Using leiningen, you can configure your project using a configuration file, project.clj. On this file you may require remotely (maven-)published jars, and by running lein deps you will get a "lib" directory with all the jars. Since the lein swank command uses that directory as a classpath, all you have to do is to add your jars to that directory.
That said, if you're still using \M-x swank-clojure-project, it will also detect your jars under that directory.
However, if you're just using a plain \M-x slime to fire a clojure repl, then I think there's no "clean" solution (aside from adding the path to your global environment's $CLASSPATH or to use some elisp voodoo - like the one in seh's answer - to change the java vm command arguments. But I believe this is only intended to do some quite basic experiments, and shouldn't be used for any project-based work (exactly for this reason!)
If you're willing to hard-code the list of Jar files, this Emacs Lisp form should suffice:
(let ((base-path "/Users/smcho/.swank-clojure"))
(setq swank-clojure-classpath
(append
swank-clojure-classpath
(mapcar (lambda (d)
(expand-file-name d base-path))
'("clojure-1.1.0-master-20091202.150145-1.jar"
"clojure-contrib-1.1.0-master-20091212.205045-1.jar"
"swank-clojure/swank-clojure-1.1.0.jar")))))
That takes your list of Jar files and adds them to the variable swank-clojure-classpath. Note that this form must be evaluated by Emacs, not SLIME's Swank. It's used by Emacs to start up the Java process that will run Clojure and Swank within it.
There are more elaborate ways to set up the class path for a project, such as including Maven-style paths below a designated project root directory.