When reading clojure -h* I found the --main option:
main options:
-m, --main ns-name Call the -main function from a namespace with args
Having the following code:
(defn -main
"I don't do a whole lot ... yet."
[& args]
(println "Hello, World!"))
Is it possible to utilize the --main argument to call directly the -main function without using lein?
*clojure = java ${JAVA_OPTS} -jar path_to_clojure.jar "$#"
Yes. Assuming -main function is in the file ./src/foo/core.clj the following will run it:
java -cp "path_to_clojure.jar:src" clojure.main --main foo.core (note the src in the classpath)
Related
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.
I have this code:
(ns test
(:gen-class))
(defn -main
[& args]
(println "hello!"))
But when I run java -cp clojure-1.6.0/clojure-1.6.0.jar clojure.main test.clj I get no output. Why? How to fix this?
You call the -main function like so:
java -cp clojure-1.6.0/clojure-1.6.0.jar clojure.main -i test.clj -m test
-i loads up a file
-m launches the -main function in a namespace
Both ns and defn do not output anything. If you would like to print "hello!" by invoking the -main function, you have to add a function call at the end of the test.clj file.
(ns test
(:gen-class))
(defn -main
[& args]
(println "hello!"))
(-main)
I am following along with this example on creating a simple web service in Clojure using ring and jetty.
I have this in my project.clj:
(defproject ws-example "0.0.1"
:description "REST datastore interface."
:dependencies
[[org.clojure/clojure "1.5.1"]
[ring/ring-jetty-adapter "0.2.5"]
[ring-json-params "0.1.0"]
[compojure "0.4.0"]
[clj-json "0.5.3"]]
:dev-dependencies
[[lein-run "1.0.0-SNAPSHOT"]])
This in script/run.clj
(use 'ring.adapter.jetty)
(require '[ws-example.web :as web])
(run-jetty #'web/app {:port 8080})
And this in src/ws_example/web.clj
(ns ws-example.web
(:use compojure.core)
(:use ring.middleware.json-params)
(:require [clj-json.core :as json]))
(defn json-response [data & [status]]
{:status (or status 200)
:headers {"Content-Type" "application/json"}
:body (json/generate-string data)})
(defroutes handler
(GET "/" []
(json-response {"hello" "world"}))
(PUT "/" [name]
(json-response {"hello" name})))
(def app
(-> handler
wrap-json-params))
However, when I execute:
lein run script/run.clj
I get this error:
No :main namespace specified in project.clj.
Why am I getting this and how do I fix it?
You're getting this error because the purpose of lein run (according to lein help run) is to "Run the project's -main function." You don't have a -main function in your ws-example.web namespace, nor do you have a :main specified in your project.clj file, which is what lein run is complaining about.
To fix this, you have a few options. You could move the run-jetty code to a new -main function of the ws-example.web function and then say lein run -m ws-example.web. Or you could do that and also add a line :main ws-example.web to project.clj and then just say lein run. Or you could try using the lein exec plugin to execute a file, rather than a namespace.
For more info, check out the Leiningen Tutorial.
You have to put that (run-jetty) stuff into a -main somewhere and then add it to the project.clj like
:main ws-example.core)
From lein help run:
USAGE: lein run -m NAMESPACE[/MAIN_FUNCTION] [ARGS...]
Calls the main function in the specified namespace.
So, you would need to put your script.clj somewhere on the project source path and then call it as:
lein run -m script
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?
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