Compiling Clojure? - clojure

I'm feeling slightly silly here, but I can't get Clojure Hello World to compile.
Directory structure:
hello-world/
clojure-1.1.0.jar
build/
classes/
src/
test/
hello.clj
hello.clj:
(ns test.hello
(:gen-class))
(defn -main [& args]
(println "Hello" (nth args 0)))
Interaction:
$ cd hello-world
[hello-world]$ java -cp ./clojure-1.1.0.jar:./build/classes:./src clojure.main
Clojure 1.1.0
user=> (require 'test.hello)
nil
user=> (test.hello/-main "there")
Hello there
nil
user=> (compile 'test.hello)
java.io.IOException: No such file or directory (hello.clj:2)
user=> *compile-path*
"classes"
user=> (doseq [p (.split (System/getProperty "java.class.path") ":")] (println p))
./clojure-1.1.0.jar
./build/classes
./src
nil
So I can load and call the file from the REPL, but it doesn't compile.
According to clojure.org, compilation needs
namespace must match classpath-relative file path - check
*compile-path* must be on the classpath - check
:gen-class argument to the ns form - check
I found this post from a year back, as far as I can tell I'm doing exactly the same, but it doesn't work.
What am I missing?
System: OS X 10.6, Java 1.6.0, Clojure 1.1

Got it, there's a fourth requirement:
*compile-path* is resolved relative to the JVMs working directory, normally the directory where java is started. Or by REPL: (System/getProperty "user.dir"),
So this works:
user=> (set! *compile-path* "build/classes")
"build/classes"
user=> (compile 'test.hello)
test.hello

Why you don't use Leiningen? It's much easier to use it, than compile code manually. You can use my article about it as introduction...

To run clojure file
clojure filename.clj

Related

How to use libraries in Clojure in LightTable

I have the following Clojure code in LightTable
(ns exercise
(:require [clojure.string :as str]))
(defn -main
[& args]
(def str1 "Hello world")
(str/includes? str1 "world")
)
When i try to run it i get the following exception:
clojure.lang.Compiler$CompilerException: java.lang.RuntimeException: No such var: str/includes?
Am i importing the library wrong or is something else wrong ?
You're probably using an old Clojure version. includes? was added in 1.8.

Spyscope Java RuntimeException No reader function for tag spy/p

I'm trying out spyscope, and following the documented example, I'm getting:
user=> (take 20 (repeat #spy/d (+ 1 2 3)))
RuntimeException No reader function for tag spy/d clojure.lang.LispReader$CtorReader.readTagged (LispReader.java:1245)
RuntimeException Unmatched delimiter: ) clojure.lang.Util.runtimeException (Util.java:221)
RuntimeException Unmatched delimiter: ) clojure.lang.Util.runtimeException (Util.java:221)
My ~/.lein/profile.clj is:
{:user {:dependencies [[spyscope "0.1.6"]]
:injections [(require 'spyscope.core)
(use 'clojure.tools.trace)]
:plugins [[lein-try "0.4.3"]]
}
}
My version of Leiningen is:
$ lein --version
Leiningen 2.8.1 on Java 1.8.0_212 OpenJDK 64-Bit Server VM
I can't seem to find any answers on how to resolve this.
Answering my own question to make it easier for the next person to looking for the solution.
The answer can be traced to [this issue]: (https://github.com/dgrnbrg/spyscope/issues/8)
Lein 2 allows users to fire lein repl in a non project directory and that's the case
You have to use spyscope within a directory with a project.clj file.
You can use spyscope this way at your profiles.clj
; try/catch to workaround an issue where `lein repl` outside a project dir
; will not load reader literal definitions correctly:
(try (require 'spyscope.core)
(catch RuntimeException e))

error in process filter: stack overflow in regexp matcher

I am trying to execute this piece of code:
(rest (file-seq (file (str "corpus/" "ham"))))
I want to get all files from "corpus/ham" directory, but I am getting this error: "error in process filter: stack overflow in regexp matcher".
Works for me:
(ns tst.demo.core
(:require [clojure.java.io :as io]))
with result:
-------------------------------------
Clojure 1.8.0 Java 1.8.0_161
-------------------------------------
(rest (file-seq (io/file (str "test/" "clj")))) =>
(#object[java.io.File 0x71c8e40e "test/clj/tst"]
#object[java.io.File 0x65a44d8a "test/clj/tst/demo"]
#object[java.io.File 0x7c3ccb39 "test/clj/tst/demo/core.clj"])
What is your environment? OS, clj & java version, etc? It also works on
Clojure 1.10.0 Java 11
I have tried the same on macOS, IntelijIdea community, Java 1.8 and Clojure 1.9
I see files present directory.

Clojure CLR with multiple namespaces

I wrote a small namespace to do some database operations and I would like to use it from within another namespace. Normally having the files in the same directory and then doing
(ns program (:require [other-ns :as other]) (:gen-class))
would be all that's necessary. However this doesn't work in Clojure CLR, compiler complains about not knowing about other-ns. So what is the proper method of doing this? Having a seperate assembly for every namespace?
[EDIT] Another example
another.clj
(ns another)
(defn hello [name] (str "Hello " name))
program.clj
(ns program
(:require [another :as a])
(:gen-class))
I load up program.clj in the repl and get this message:
FileNotFoundException Could not locate another.clj.dll or another.clj on load path. clojure.lang.RT.load (d:\work\clojure-clr\Clojure\Clojure\Lib\RT.cs:3068)
I created two files in the same directory filea.clj and fileb.clj. Here's filea.clj:
(ns filea)
(defn hi []
(println "hi from filea"))
Here's fileb.clj:
(ns fileb
(require [filea :as a])
(:gen-class))
(defn -main []
(println "hi from fileb")
(a/hi))
I then changed into the directory where these files live and ran:
C:\temp\multi-ns>clojure.compile fileb
Compiling fileb to . -- 59 milliseconds.
And when I ran it I saw:
C:\temp\multi-ns>c:\Tools\clojure-clr-1.3.0-Debug-4.0\fileb.exe
hi from fileb
hi from filea
Are you using vsClojure or writing your code outside of VS?

Problem using redis-clojure with Leiningen

Hey, I'm new to Clojure and Leiningen and a bit stuck. I've managed to setup a project with Leiningen. I'm able to compile it into an uberjar and run the repl. I've also managed to load a dependency named aleph to run a simple concurrent webserver.
The next step for me is to use redis-clojure to access redis. But here I'm stuck. This is my project.clj:
(defproject alpha "0.0.1-SNAPSHOT"
:description "Just an alpha test script"
:main alpha.core
:dependencies [[org.clojure/clojure "1.2.0"]
[org.clojure/clojure-contrib "1.2.0"]
[aleph, "0.1.2-SNAPSHOT"]
[redis-clojure "1.2.4"]])
And here is my core.clj: Note that I only added the line (:requre redis) according to the example from redis-clojure.
(ns alpha.core
(:require redis)
(:gen-class))
(use `aleph.core 'aleph.http)
(defn alpha [channel request]
(let [] (enqueue-and-close channel
{:status 200
:header {"Content-Type" "text/html"}
:body "Hello Clojure World!"}))
(println (str request)))
(defn -main [& args]
(start-http-server alpha {:port 9292}))
When I try to run lein repl this happens:
java.io.FileNotFoundException: Could not locate redis__init.class or redis.clj on classpath: (core.clj:1)
Yes, I have run lein deps and the redis-clojure jar is available in my lib directory. I'm probably missing something trivial, but I've been at this issue for a few hours now and not getting any closer to a solution. Thanks!
Namespace redis does not exist. I suppose you need
(:require [redis.core :as redis])
A way to check for available namespaces:
(use 'clojure.contrib.find-namespaces)
(filter #(.startsWith (str %) "redis") (find-namespaces-on-classpath))
This works with more current versions of Clojure, in this example it finds the names of all namespaces that contains the sub string "jdbc":
(map str
(filter
#(> (.indexOf (str %) "jdbc") -1)
(all-ns)))
The result is a sequence, in example:
=>
("clojure.java.jdbc")