rand-nth always yields the same result after compilation - clojure

I've project created via Leiningen with core.clj:
(ns cotd.core
(:gen-class)
(:use [clojure.repl :only (doc)]))
(defmacro eval-doc
[form]
(let [resulting-symbol (eval form)]
`(doc ~resulting-symbol)))
(defn- random-function-name []
(rand-nth (keys (ns-publics 'clojure.core))))
(defn -main
"Display random doc page"
[& args]
(eval-doc (random-function-name)))
And after compiling and running it always yields the same result:
$ java -jar cotd.jar
-------------------------
clojure.core/unchecked-negate
([x])
Returns the negation of x, a long.
Note - uses a primitive operator subject to overflow.
$ java -jar cotd.jar
-------------------------
clojure.core/unchecked-negate
([x])
Returns the negation of x, a long.
Note - uses a primitive operator subject to overflow.
But with two consecutive calls:
(do
(eval-doc (random-function-name))
(eval-doc (random-function-name))))
It yields two different results in single "call".
What I've tried is googling, reading, etc. but I have no clues what's going on...
How to invoke this rand-nth dynamically?

The problem wasn't with rand-nth but because the resulting-symbol in the let statement is produced during the compilation phase. #beyamor provided answer here: Unable to get random (doc) from a namespace

Related

How to run clojure program from terminal

I have just begun learning clojure and I'm using the Textmate editor for writing the scripts. However, I am not able to figure out how to run it from the terminal. Like I type the clj filename.clj command but nothing happens. Do I need to include the function name also somewhere because I have a function that takes a number as an argument.
Here is my code that I want to run from the terminal:
(defn next-collatz-num [n]
(if (even? n)
(quot n 2)
(inc (* n 3))))
(defn collatz [n]
(take-while #(< 1 %)(iterate next-collatz-num n)))
(defn max-count-collatz [n]
(when (> n 0)
(first
(reduce
#(if (> (last %1)(last %2)) %1 %2)
[1 1] (map #(list % (count (collatz %))) (range 1 (inc n)))))))
(max-count-collatz 999999)
Clojure has a much more interactive environment than just running a whole script at the terminal command prompt.
TL;DR, install leiningen, create a project.clj, then run lean repl.
If you don't want to create a project.clj, or if you're curious how to do it the hard way, read on...
You can start a Clojure read-eval-print-loop (REPL) interactive prompt with
java -cp clojure-1.6.0.jar clojure.main
(download the latest Clojure jar here).
Once you're in the REPL, load the code file:
(load-file "my-script.clj")
Now, you can call the function directly:
(max-count-collatz 5)
If it doesn't work as you'd expect, change the code, save and reload it in the REPL:
(require 'my-script :reload-all)
While it is possible to run individual Clojure files using Clojure.jar, one of the best things about Clojure is the leiningen dependency manager and build tool. Creating a project is easy, and for anything more than a single file with no external dependencies, it is a huge improvement over using java and Clojure.jar directly.

MorphAnnotator.addLemma produces a NullPointerException for a particular text stream

(def ^:private props
(doto (java.util.Properties.)
(.put "annotators" "tokenize, ssplit, pos, lemma, parse")
(.put "parse.maxlen" (str (-> config :nlp :max-sentence-length)))
(.put "pos.maxlen" (str (-> config :nlp :max-sentence-length)))))
(def ^:private pipeline (StanfordCoreNLP. props))
(defn- annotated-doc [s]
(.process pipeline s))
(def input-text (slurp "/home/you/some.txt"))
(annotated-doc input-text)
Which then produces either a properly annotated result as expected or it produces this exception:
java.lang.NullPointerException: null
MorphaAnnotator.java:68 edu.stanford.nlp.pipeline.MorphaAnnotator.addLemma
MorphaAnnotator.java:55 edu.stanford.nlp.pipeline.MorphaAnnotator.annotate
AnnotationPipeline.java:67 edu.stanford.nlp.pipeline.AnnotationPipeline.annotate
StanfordCoreNLP.java:881 edu.stanford.nlp.pipeline.StanfordCoreNLP.annotate
StanfordCoreNLP.java:910 edu.stanford.nlp.pipeline.StanfordCoreNLP.process
(Unknown Source) sun.reflect.GeneratedMethodAccessor27.invoke
DelegatingMethodAccessorImpl.java:43
sun.reflect.DelegatingMethodAccessorImpl.invoke
Method.java:606 java.lang.reflect.Method.invoke
Reflector.java:93 clojure.lang.Reflector.invokeMatchingMethod
Reflector.java:28 clojure.lang.Reflector.invokeInstanceMethod
The text file is very vanilla. I have reduced my annotators list down to what produces the issue. I have 6 GB of memory configured for it. The text file is 3886 characters long, UTF-8 BOM formatted file. It works with partial text from this file just fine. It even works if I take the whole file as in (take 3886 input-text). So I'm stumped. Not sure what to make of it. Any suggestions?
Here is a link to the text file I was using: http://nectarineimp.com/spooky-action.txt
From my project.clj file:
:dependencies [[org.clojure/clojure "1.6.0"]
[edu.stanford.nlp/stanford-corenlp "3.3.1"]
[edu.stanford.nlp/stanford-corenlp "3.3.1" :classifier "models"]]
I agree that this is was a bug in the Annotator. I'm not sure what your configuration settings were for:
(def ^:private props
(doto (java.util.Properties.)
(.put "annotators" "tokenize, ssplit, pos, lemma, parse")
(.put "parse.maxlen" (str (-> config :nlp :max-sentence-length)))
(.put "pos.maxlen" (str (-> config :nlp :max-sentence-length)))))
But they were irrelevant in reproducing the issue. I recently upgraded a project to version 3.5.2 and your code block ran without issues (CoreNLP Version History).
Running in 3.1.1 produces your results exactly. It looks like at version 3.5.0 a Java 1.8 JVM is required.
This bug appears to be fixed in version 3.4 of CoreNLP as well, which doesn't require JVM updates.
Your question was posted a while ago, so I'm pretty sure you've already figured all this out, but for the sake of Google, I've left these comments.

What happens to second println statement? (Clojure repl)

When I call this small function in the clojure REPL it only prints the first hello world, not hello mars. Why is that? It's not lazy (as far as I understand) otherwise the exception wouldn't get hit, in addition SO tells me println causes a flush.
(defn foo
"I don't do a whole lot."
[x]
(println x "Hello, World!")
(map (fn [x] (let [_ (println "Hello, Mars")
__ (throw (Exception. "talking to many planets"))]
{ :aliens? false }
)) [1 2 3])
)
Output:
(foo nil) nil Hello, World!
Exception talking to many planets test.repl/foo/fn--6580
(form-init13300486174634970.clj:5)
First of all, map is actually lazy, so foo returns a LazySeq, which is then forced when the REPL prints it. Now when I run your example using bare Clojure (java -jar clojure.jar), I get the following output:
user=> (foo nil)
nil Hello, World!
(Hello, Mars
Exception talking to many planets user/foo/fn--1 (NO_SOURCE_FILE:5)
user=>
I get the same result with both Clojure 1.4.0 and 1.5.1.
Now if I run via lein repl, I get the output you describe. So it appears that something in the nrepl chain is affecting how things are printed. This makes sense since nrepl is designed to communicate with clients over the network. There appears to be a slight bug, however, in its handling of this case. Or perhaps it re-binds flush-on-newline to false when printing the value? Sorry, I haven't dived into the code deep enough to give a more definite answer.
Incidentally, if you wrap the function call in a println, i.e. (println (foo nil)), then you get the expected output shown above.
Okay I have an idea. Map returns a lazy seq. The repl calls println (or similar) on the map which attempts to realize it, calling .toString() (or similar). Internally when print/ln is called within a print/ln it saves the output until its finishes it own, thus an exception will mean the other bits collected (print within a print) call aren't flushed.

In Clojure passing a open file pointer into functions

In Conjure, I need to read in a long file, too long to slurp in, and I wish to pass the open file pointer into method, which I can call recursively, reading until it is empty. I have found examples using open-with, but is there a way to open a file and then read from it inside of a function? Points to examples or docs would be helpful.
Is this along the lines of what you have in mind?
(defn process-file [f reader]
(loop [lines (line-seq reader) acc []]
(if (empty? lines)
acc
(recur (rest lines) (conj acc (f (first lines)))))))
(let [filename "/path/to/input-file"
reader (java.io.BufferedReader. (java.io.FileReader. filename))]
(process-file pr-str reader))
Note that if you (require '[clojure.java.io :as io]) you can use io/reader as a shortcut for invoking BufferedReader and FileReader directly. However, using with-open would still be preferable - it will ensure the file is closed properly, even in the event of an exception - and you can absolutely pass the open reader to other functions from within a with-open block.
Here's how you could make use of with-open in the scenario you use in the answer you've posted, passing the reader and writer objects to a function:
(with-open [rdr (io/reader "/path/to/input-file")]
(with-open [wtr (io/writer "/path/to/output-file")]
(transfer rdr wtr)))
I should also note that in my example scenario it would be preferable to map or reduce over the line-seq but I used loop/recur since you asked about recursion.
Here's the ClojureDocs page on the clojure.java.io namespace.
Playing around I discovered the answer, so for any others looking, here is a version of my solution.
(defn transfer
[inFile outFile]
(.write outFile (.read inFile))
...
...
(transfer (clojure.java.io/reader "fileIn.txt)
(clojure.java.io/writer "out.txt"))

Downloading image in Clojure

I'm having trouble downloading images using Clojure, there seems to be an issue with the way the following code works: -
(defn download-image [url filename]
(->> (slurp url) (spit filename)))
This will 'download' the file to the location I specify but the file is unreadable by any image application I try to open it with (for example, attempting to open it in a web browser just return a blank page, attempting to open it in Preview (osx) says it's a corrupted file)
I'm thinking this is might be because slurp should only really be used for text files rather than binary files
Could anyone point me in the right direction for my code to work properly? Any help would be greatly appreciated!
slurp uses java.io.Reader underneath, which will convert the representation to a string, and this is typically not compatible with binary data. Look for examples that use input-stream instead. In some ways, this can be better, because you can transfer the image from the input buffer to the output buffer without having to read the entire thing into memory.
edit
Since people seem to find this question once in awhile and I needed to rewrite this code again. I thought I'd add an example. Note, this does not stream the data, it collects it into memory and returns it an array of bytes.
(require '[clojure.java.io :as io])
(defn blurp [f]
(let [dest (java.io.ByteArrayOutputStream.)]
(with-open [src (io/input-stream f)]
(io/copy src dest))
(.toByteArray dest)))
Test...
(use 'clojure.test)
(deftest blurp-test
(testing "basic operation"
(let [src (java.io.ByteArrayInputStream. (.getBytes "foo" "utf-8"))]
(is (= "foo" (-> (blurp src) (String. "utf-8")))))))
Example...
user=> (blurp "http://www.lisperati.com/lisplogo_256.png")
#<byte[] [B#15671adf>