I am trying to run the following program on my Mac:
(ns clojure.examples.hello
(:gen-class))
(require ‘clojure.java.io’)
(defn Example []
(.exists (file "Example.txt")))
(Example)
I do this wih the following command:
clojure Exists.clj
But this gives me the following error:
Syntax error (ClassNotFoundException) compiling at (Exists.clj:5:1).
‘clojure.java.io’
How can I go about including the clojure.java.io class?
Here is how you would normally write this in a source code file:
(ns tst.demo.core
(:require [clojure.java.io :as io]) ; proper form, but not used anywhere
(:import [java.io File]))
(println (spit "demo.txt" "stuff happens"))
(println (slurp "demo.txt"))
(println (.exists (java.io.File. "./demo.txt"))) ; will work w/o `:import` above
(println (.exists (File. "./demo.txt"))) ; requires `:import` declaration above
with results:
(spit "demo.txt" "stuff happens") => nil
(slurp "demo.txt") => "stuff happens"
(.exists (java.io.File. "./demo.txt")) => true
(.exists (File. "./demo.txt")) => true
Note that using the :require keyword in a ns form requires different syntax and quoting than using the (require ...) function call.
If you are typing these lines into a REPL, you may do something like:
demo.core=> (ns demo.core)
nil
demo.core=> (require '[clojure.java.io :as io]) ; function-call version
nil
demo.core=> (spit "demo.txt" "stuff happens")
nil
demo.core=> (println (slurp "demo.txt"))
stuff happens
nil
You may find this template project helpful in getting started. Also be sure to check out the list of documentation sources, esp. the Clojure CheatSheet!
Related
When I start a repl with lein repl I can run the function greet and it works as expected.
(ns var-test.core
(:gen-class))
(declare ^:dynamic x)
(defn greet []
(binding [x "Hello World."]
(println (load-string "x"))))
(defn -main [& args]
(greet))
But if run the code via lein run it fails with
java.lang.RuntimeException: Unable to resolve symbol: x in this context.
What am I missing?
Is the var x dropped during compilation, despite being declared, since it is never used outside of the string?
Edit:
Solution
#amalloy's comment helped me understand I need to bind *ns* in order load the string within the expected namespace, instead of a new, empty namespace.
This works as expected:
(ns var-test.core
(:gen-class))
(declare ^:dynamic x)
(defn greet []
(binding [x "Hello World."
*ns* (find-ns 'var-test.core)]
(println (load-string "x"))))
(defn -main [& args]
(greet))
Wow, I've never seen that function before!
According to the docs, load-string is meant to read & load forms one-at-a-time from an input string. Observe this code, made from my favorite template project:
(ns tst.demo.core
(:use tupelo.core tupelo.test)
(:require [tupelo.string :as str]))
(dotest
(def y "wilma")
(throws? (eval (quote y)))
(throws? (load-string "y"))
So it appears that load-string starts with a new, empty environment, then reads and evaluates forms one at a time in that new env. Since your x is not in that new environment, it can't be found and you get an error.
Try it another way:
(load-string
(str/quotes->double
"(def ^:dynamic x)
(binding [x 'fred']
(println :bb (load-string 'x'))) " ))
;=> :bb fred
In this case, we give all the code as text to load-string. It reads and eval's first the def, then the binding & nested load-string forms. Everything works as expected since the working environment contains the Var for x.
Some more code illustrates this:
(spy :cc
(load-string
"(def x 5)
x "))
with result
:cc => 5
So the eval produces the var x with value 5, then the reference to x causes the value 5 to be produced.
To my surprise, the partial load-string works in a fresh REPL:
demo.core=> (def x "fred")
#'demo.core/x
demo.core=> (load-string "x")
"fred"
So load-string must be coded to use any pre-existing
REPL environment as the base environment. When using lein run, there is no REPL environment available, so load-string starts with an empty environment.
I'm trying require clojure.algo.monads, I'm a little confused with clojure import/require/use
; at lein...
:main monads.core/-main
:dependencies [[org.clojure/clojure "1.6.0"]
[org.clojure/algo.monads "0.1.5"]])
install deps: lein deps
and this simpele code to test
(ns monads.core
(require clojure.algo.monads))
(defn -main [& args]
(clojure.algo.monads)
(println "Hello, World!"))
lein run
Exception in thread "main" java.lang.ClassNotFoundException: clojure.algo.monads, compiling:(monads/core.clj:6:3)
at clojure.lang.Compiler.analyze(Compiler.java:6464)
at clojure.lang.Compiler.analyze(Compiler.java:6406)
at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3665)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6646)
...
I'm doing something wrong?
The expression (clojure.algo.monads) in your -main function is considered a call to clojure.algo.monads, which should be either a special form, a macro, or a function. However, clojure.algo.monads is a namespace. There is no Java class file corresponding to it. This results in ClassNotFoundException.
I suggest that you require the clojure.algo.monads namespace and refer only limited functions or macros that you want to use. Here is an example.
user> (require '[clojure.algo.monads :refer [domonad maybe-m]])
nil
user> (defn f
[x]
(domonad maybe-m
[a x
b (inc x)]
(* a b)))
#'user/f
user> (f 3)
12
user> (f nil)
nil
I'm trying to build a small om-component that uses goog.fx.Dragger to make a target draggable. I require goog.fx.Dragger :as dragger and like so:
(ns om-draggable-me.core
(:require [om.core :as om :include-macros true]
[om.dom :as dom :include-macros true]
[goog.fx.Dragger :as dragger]))
When i use it like:
(defn draggable [app owner]
(reify
om/IDidMount
(did-mount [_]
(let [target (om/get-node owner)]
(dragger. target)))
om/IRender
(render [_]
(dom/div #js {:id "drag-box" :className "drag-box"}))))
I get the compiler warning:
WARNING: Use of undeclared Var om-draggable-me.core/dragger at line 22 src/cljs/om_draggable_me/core.cljs
Seen other examples of the use of goog.fx.DragDrop so why does not this work?
In your require form, dragger is a namespace alias
[goog.fx.Dragger :as dragger]
which is intended to be used like this:
dragger/your-var
;; the same as goog.fx.Dragger/your-var
while in your script, it was used as if it's a var:
(dragger. target)
and, as the compiler complained, such var hasn't been defined.
You can see people refer to clojure.string like this:
(require '[clojure.string :as str])
without worrying about conflicting with clojure.core/str function:
(str/join ", " [1 2 3])
(str "hello" "world")
For some reason the alias did not work, it works with fully qualified name:
(did-mount [_]
(let [target (om/get-node owner)]
(goog.fx.Dragger. target)))
I have the following clojure code (trying to write / get entries from redis):
(ns hello.core2)
(ns h hello.core2 (:require [taoensso.carmine :as car]))
(def pool (car/make-conn-pool))
(def spec-server1 (car/make-conn-spec))
(defmacro wcar [& body] `(car/with-conn pool spec-server1 ~#body))`
(defn -main
(wcar (car/ping)
(car/set "foo" "bar")
(car/get "foo")))
I get the following error:
Exception in thread "main" java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol
at clojure.lang.RT.seqFrom(RT.java:487)
at clojure.lang.RT.seq(RT.java:468)
Any idea what im doing wrong?
(defn -main ...): you forgot the argument vector for the function -main; it should be (defn -main [& args] ...).
The problem is probably this:
(ns h hello.core2 (:require [taoensso.carmine :as car]))
There should be only one namespace declaration, like this (so also move the first ns expression):
(ns hello.core2
(:require [taoensso.carmine :as car]))
I'm trying to understand the -main and its namespace settings. The default namespace in a -main function seems to be "user", but function defined "above" the main function, in the same file, can be called. Are they referred? I was running this to find out:
(ns ack.doodle)
(defn fo [] "bar")
(defn -main [& args]
(println (fo)) ;; bar
(println *ns*) ;; #<Namespace user>
(println (get (ns-refers *ns*) 'sorted-map)) ;; #'clojure.core/sorted-map
(println (get (ns-refers *ns*) 'fo)) ;; nil
(println (get (ns-map *ns*) 'fo)) ;; nil
(println (get (ns-publics *ns*) 'fo)) ;; nil
(println (get (ns-interns *ns*) 'fo)) ;; nil
(println (get (ns-aliases *ns*) 'fo)) ;; nil
(println (ns-resolve *ns* 'fo))) ;; nil
The call (fo) succeeds, yet apparently the symbol 'fo is not known in the current namespace *ns*. What's going on?
This problem hit me when trying to pass the name of some function, along with some arguments, as command line arguments to -main.
steps to reproduce
paste above code in a file ./src/ack/doodle.clj
create ./project.clj with these contents:
(defproject ack "1" :main ack.doodle)
run it:
lein run
It looks like leiningen runs (-main) by calling it from user namespace like that: (ack.doodle/-main). Thus *ns* is bound to the user namespace.
Try running lein repl in your project root. Then run (-main) and see what happens. :)
Didn't I answer this for you last night in #clojure? If there's something unsatisfying about the answer, you'll have to clarify your question.