Clojure function will not compile - clojure

Please excuse my complete lack of knowledge, but why doesn't this function compile?
(defn add-onehundred
[num]
(+ num 100))
(add-onehundred 5)
I get this error thrown in the terminal:
Exception in thread "main" Syntax error compiling at (/private/var/folders/ls/j5fjkkb96mx340pb_gm12t740000gn/T/form-init13922061526950471210.clj:1:126).
at clojure.lang.Compiler.load(Compiler.java:7647)
at clojure.lang.Compiler.loadFile(Compiler.java:7573)
at clojure.main$load_script.invokeStatic(main.clj:452)
at clojure.main$init_opt.invokeStatic(main.clj:454)
at clojure.main$init_opt.invoke(main.clj:454)
at clojure.main$initialize.invokeStatic(main.clj:485)
at clojure.main$null_opt.invokeStatic(main.clj:519)
at clojure.main$null_opt.invoke(main.clj:516)
at clojure.main$main.invokeStatic(main.clj:598)
at clojure.main$main.doInvoke(main.clj:561)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.lang.Var.applyTo(Var.java:705)
at clojure.main.main(main.java:37)
Caused by: java.lang.Exception: Cannot find anything to run for: clojure-noob.core
at user$eval140.invokeStatic(form-init13922061526950471210.clj:1)
at user$eval140.invoke(form-init13922061526950471210.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:7176)
at clojure.lang.Compiler.eval(Compiler.java:7166)
at clojure.lang.Compiler.load(Compiler.java:7635)
... 12 more
full code as in the editor here, when main is commented out it will not compile, when it isn't commented out add-onehundred returns nothing:
(ns clojure-noob.core
(:gen-class))
; (defn -main
; "I don't do a whole lot ... yet."
; [& args]
; (println "Hello, Mate"))
(defn add-onehundred
[num]
(+ num 100))
(add-onehundred 5)

Based on the error message, you're trying to run this with:
lein run
and you have the following in your project.clj file:
:main clojure-noob.core
or:
:main ^:skip-aot clojure-noob.core
This tell Leiningen to look for a -main function in the clojure-noob.core namespace in order to "run" your new application -- but you've commented it out, so Leiningen cannot find it, hence "Cannot find anything to run for: clojure-noob.core".
Uncomment your -main and have it call add-onehundredand print the result. Note that functions in Clojure must be defined (or at least declared) before they are used, so your code will end up looking like this:
(ns clojure-noob.core
(:gen-class))
(defn add-onehundred
[num]
(+ num 100))
(defn -main
"I don't do a whole lot ... yet."
[& args]
(println (add-onehundred 5)))
lein run should run your app and print 105.

Related

Clojure: Could not locate System/IO/File__init.class, System/IO/File.clj or System/IO/File.cljc on classpath

I am trying to run the following code that cuts a .csv file (can be thought of as plaintext) down to 100 lines:
(ns tst.demo.core
(:require [clojure.java.io :as io] [System.IO.File])
(:import [java.io File]))
(defn lines [n filename]
(with-open [rdr (io/reader filename)]
(doall (take n (line-seq rdr)))))
(defn spit-lines [^String filename a-seq]
(->> a-seq
(System.Linq.Enumerable/Cast (type-args System.String))
(System.IO.File/WriteAllLines filename)))
(spit-lines(lines 100 "test_set_batch1.csv")))
Whenever I run this I get the following error:
Syntax error (FileNotFoundException) compiling at (RemoveAfterLine100.clj:1:1).
Could not locate System/IO/File__init.class, System/IO/File.clj or System/IO/File.cljc on classpath.
I'm confused as to what's causing this error. I added System.IO.File to the :requires, so I thought it should work.
As #mange and #Alan Thompson pointed out, my problem is that I was trying to run a script on both CLR and JVM.

clojure.java.io ClassNotFoundException

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!

Why does the macroexpand does not print the results of defmacro?

I am a newbie to Clojure and currently trying to invoke a simple macro using defmacro and macroexpand.
(ns tutorial.core
(:gen-class)) ; namespace
(defn -main [& args]
(defmacro Simple [] (println "Hello"))
(macroexpand '(Simple))
)
Is there something I have missed? it seems the program runs without any problems but the results are not coming out as expected.
I expect the results to print out as Hello, but no outputs result from this script.
Preface:
Please see this past question for an overview of the best way to write a macro (IMHO).
Answer:
You shouldn't define the macro in the main function. Try this:
(ns demo.core)
(defmacro happy
[]
`(println "I'm happy!")) ; *** notice the backtick! ***
(defn -main [& args]
(println :expanded (macroexpand '(happy)))
(happy)
)
start up a repl:
~/expr/demo > lein repl
demo.core=> (macroexpand '(happy))
;=> (clojure.core/println "I'm happy!")
and we see that it works. Try running from the command line:
~/expr/demo > lein run
:expanded (happy) ; <= ***** OOOPS! *****
I'm happy!
Try changing the single-quote into a syntax-quote (aka backtick), then run:
(defn -main [& args]
(println :expanded (macroexpand `(happy)))
(happy))
~/expr/demo > lein run
:expanded (clojure.core/println I'm happy!)
I'm happy!
The explanation is that the syntax-quote will fully-qualify the Var happy => demo.core/happy (you can see the same effect on the println Var inside of the happy macro itself because of that syntax-quote). This allows the macroexpand to work properly. Compare with a single-quote:
(defn -main [& args]
(println :expanded (macroexpand '(demo.core/happy)))
(happy))
~/expr/demo > lein run
:expanded (clojure.core/println I'm happy!)
I'm happy!
The cause of this behavior is that, in the REPL, we see from the prompt that we are in the demo.core namespace, so happy is resolved as demo.core/happy. When we use lein run, however, observe:
(defn -main [& args]
(println *ns*)
(println (ns-name *ns*)))
with result:
~/expr/demo > lein run
*ns* => #object[clojure.lang.Namespace 0xb625b00 "user"]
(ns-name *ns*) => user
and we see that the *ns* is set to the user namespace and happy cannot be resolved to the Var demo.core/happy unless we fully qualify it either manually or using syntax-quote in the code.
You can find a list of documentation here. Be sure especially to study the Clojure CheatSheet.
For macros, the book Mastering Clojure Macros is also good.
Your macro function doesn't return code, but does the printing immediately. This is very bad style as it has unforeseen consequences.
If you were to use this is a function:
(defn hello [] (Simple))
It prints "Hello" when the function is created. The code being inserted in the function is the result fo println which is nil, thus you have created this:
(defn hello [] nil)
Then if you call hello 3 times none of the calls will no any printing since your macro doesn't produce anything else than nil. If you change your macro to return structure:
;; The quote that makes all the difference
(defmacro Simple [] '(println "Hello"))
Then if will not print anything during the createion of hello, but the expansion would be (println "Hello") and the same fucntion hello would become:
(defn hello [] (println "Hello"))

Parse Clojure Command Line Args

I am trying to separate my cli options into a stand-alone namespace for starting up an HTTP server, and I am getting this error-
clojure.lang.ArraySeq cannot be cast to java.lang.CharSequence
In main.clj, this code works fine-
(ns served.main
(:require [org.httpkit.server :refer [run-server]]
[served.app.core :refer [handler]]
[served.server.cli-options :refer [set-options]]
[clojure.tools.cli :refer [parse-opts]])
(:gen-class))
(def cli-options
[
["-p" "--port PORT" "Port number"
:default 5000
:parse-fn #(Integer/parseInt %)
:validate [#(< 0 % 0x10000) "Must be a number between 0 and 65536"]]
])
(defn -main [& args]
(println "Server starting")
(let [options (get (parse-opts args cli-options) :options)]
;;(let [options (set-options args)]
(println (str options))
(run-server handler options)))
It will work with the default options in (def cli-options) and it compiles correctly if I pass in arguments, such as -p 7000.
When I call the main function with the external namespace served.server.cli-options instead of clojure.tools.cli directly (i.e. switch the comment in main), I get the error only when passing in args.
That is, starting the server without arguments, e.g. lein run compiles fine and will print out the defaults. The error comes with lein run -p 7000.
After deleting (def cli-options) in main to avoid any global conflict, here is served.server.cli-options
(ns served.server.cli-options
(:require [clojure.tools.cli :refer [parse-opts]]))
(def cli-options
[
["-p" "--port PORT" "Port number"
:default 5000
:parse-fn #(Integer/parseInt %)
:validate [#(< 0 % 0x10000) "Must be a number between 0 and 65536"]]
])
(defn set-options [& args]
(let [options (get (parse-opts args cli-options) :options)]
(println (str options))
options))
So far as I can tell, I copied the contents to the new namespace correctly. Here are the docs for parse-opts, here is the example that I am drawing from, and a similar but different SO issue here.
My question - how are the CLI args being transformed to throw casting error, and how do I fix it?
Any help would be greatly appreciated.
Delete the & in:
(defn set-options [& args]
& wraps up any additional arguments in a seq. Since you’ve already wrapped the program arguments once in main, you mustn’t do it again in the call to set-options.

Determining Why Clojure REPL (load-file) and cake build yield error

Since Clojure 1.3, I am confused about the directory structure needed to build something in Clojure. I am using cake to build and cake repl.
Here is what works. I have a working build directory addr_verify. The main's and ns's name is addr-verify. The project.clj refers to addr-verify as main, and in addr_verify/src there is addr_verify.clj. The ns inside addr_verify.clj refers to the addr-verify name space.
Now, I had a directory mr1, but cake won't compile it right at line 1
(ns mr1
(use ['clojure.string :only '(split)])
(use ['clojure.string :only '(join)])
)
If mr1 is a bad name, what naming convention should I use?
I have tried mr1_app as a directory structure using mr1-app as the main name and ns name. I
For mr1 as the directory and ns name, I get
Caused by: clojure.lang.Compiler$CompilerException: java.lang.ClassCastException: clojure.lang.PersistentList cannot be cast to java.lang.Comparable, compiling:(mr1.clj:1)
I'm just not getting what I'm doing wrong here, and I know it's probably something really simple.
Edit:
Why does the binary mr1 not have a main?
mr1/project.clj
(defproject mr1 "0.0.1-SNAPSHOT"
:description "TODO: add summary of your project"
:dependencies [[org.clojure/clojure "1.3.0"]
[org.clojure/tools.cli "0.1.0"]]
:main mr1)
mr1/src/mr1.clj
(ns mr1
(:use [clojure.string :only [split]]
[clojure.string :only [join]]))
(def grid-dim (atom '(0 0)))
(def mr1-pos (atom '(0 0)))
(def mr2-pos (atom '(0 0)))
(defn cvt-str-to-int
[string]
(map #(Integer/parseInt %)
(split string #" ")))
(defn prompt-for-grid-dim
[]
(do
(println "Enter the dimensions of the grid (10 10) ")
(cvt-str-to-int (read-line))
))
(defn prompt-for-rover-pos
[rover-num]
(do
(println "Enter rover's initial position on the grid (2 4) ")
(cvt-str-to-int (read-line))
))
(defn prompt-for-rover-moves
[]
(do
(println "Enter rover's moves LMMRM ")
(read-line)
))
(defn -main
[& args]
(do
(reset! grid-dim (cvt-str-to-int (prompt-for-grid-dim)))
(reset! mr1-pos (cvt-str-to-int (prompt-for-rover-pos)))
)
)
Since the first part has already been answered, I will answer the part about :main.
As sample.project.clj file says, :main key should have as an assigned value a namespace which contains -main function. So you should have such function
(defn -main [& args]
(do-things-you-want-to-do-on-program-start))
in your mr1.clj. Also AFAIR if you want to use your program as a standalone jar you have to have this namespace gen-classed. By this I mean that you have to:
Include :gen-class option in your namespace definition like this:
(ns mr1
(:gen-class)
...other options...)
Make the namespace AOT-compiled (AOT stands for Ahead Of Time). To do this you need to specify your namespace in the list of AOT-compiled namespaces in project.clj:
(defproject mr1 "0.0.1-SNAPSHOT"
...other definitions...
:aot [mr1]
:main mr1)
After you've done this, you can use cake to generate executable jar for you.
ADD:
I think it is worth to note that you don't have to have a :main at all. If all you want to do is to run your program in repl or if you want to create a library, there can be no gen-classes namespaces (except if you want to interact with plain java code in such a way that java code can call your clojure code) and no :main namespace, which are required only for executable jars.
I think there is something wrong with the "syntax" of your namespace declaration. Instead, try this:
(ns mr1
(:use [clojure.string :only [split]]
[clojure.string :only [join]]))
Change your :main setting in project.clj accordingly: it should just be mr1, contrary to what I said earlier.
Edited according the comment of googolplex