How to disambiguate in Clojure - clojure

I have this function in a namespace that does not import/require/use any other packages:
(defn crash [msg]
(throw (Throwable. msg)))
Cursive (the IntelliJ IDEA IDE Plugin) highlights Throwable and gives me the message Cannot disambiguate overloads of Throwable. I get the same message with Exception and Error.
I don't understand the source of this message - I doubt that these Java classes are defined in any other jar files apart from the Java language ones. Anything I can to make this message go away?
These are in the project.clj:
:dependencies [[org.clojure/clojure "1.6.0"]
[net.mikera/imagez "0.8.0"]
[org.clojure/math.numeric-tower "0.0.4"]]

Throwable has two 1-arg constructors (doc): one expecting a String and the other expecting a Throwable.
At runtime Clojure figures it out (since, in this specific case, it's impossible for an object to be both a String and a Throwable) but this requires the use of reflection.
Adding a type-hint to msg to specify which overload you expect to use would remove the need for reflection and hopefully calms Cursive down.
(defn crash [^String msg]
(throw (Throwable. msg)))

Related

Reflection warning - Java methods error on Clojure/Leiningen

I'm new on coding. My first lang is Clojure. And it's my first question on stackoverflow.
I wrote a Clj code, tested all functions on lein(Emacs/Cider) and I want to compile for testing. But Java methods returned this error message :
(on terminal in project folder):
aaron#debian:~/img-process$ lein check
Reflection warning, img_process/core.clj:25:30 - reference to field getWidth can't be resolved.
(and getHeight, getRGB, setRGB, java.io.File, javax.imeageio.ImageIO, java.lang.String)
Why lein can not see Java elements ?
How can I compile this ?
Thank you.
project.clj
https://github.com/harununal/clj-x-ray-coloring/blob/master/project.clj
core clj :
https://github.com/harununal/clj-x-ray-coloring/tree/master/src/img_process
If Clojure cannot imply the type of a Java object, it falls back on reflection for interop which is much slower. If you use:
(set! *warn-on-reflection* true)
Then you'll see these warnings at the REPL too. If you type hint your methods, then Clojure can see the types and emit much better code. e.g.
(defn get-img-coords
[^BufferedImage img]
(for [y (range (.getHeight img))
x (range (.getWidth img))]
[x y]))
Note that lein check isn't a compiler - it's the lein equivalent of a light linter, perhaps, checking for these warnings and others.

How to define prerequisite functions in Midje?

I should start by saying I'm new to Clojure, and FP in general. I've been reading the documentation about how to define prerequisites in Midje, but I can't make sense of some of it.
My understanding was that to do top-down TDD, you're supposed to start by writing a test in your test module, with an unfinished statement at the top that 'declares' all the prerequisite functions you haven't defined yet. Then you can fiddle with those prerequisite functions in the provided function within your test (describing their return values and such).
My confusion lies in how you're supposed to get your actual source module to recognize the prerequisite functions. Here's a very simple and contrived example I'll use to illustrate my meaning:
;;; in my run_game_test module
(ns clojure-ttt.run-game-test
(:require [midje.sweet :refer :all]
[clojure-ttt.run-game :refer [start-game]]))
(unfinished do-turns)
(fact "`start-game` returns whatever `do-turns` returns"
(start-game) => ..winner..
(provided
(do-turns) => ..winner..))
And then to make the test fail properly, I just write a stub of a function in my run_game module.
(ns clojure-ttt.run-game)
(defn start-game
[])
So far so good. I run the tests and they fail because:
a) do-turns isn't getting called
b) start-game isn't returning anything.
So now to make the test pass, by changing start-game to call and return (do-turns). For the record, do-turns is a hypothetical prerequisite function that I'm going to get from a not-yet-existing module--which, as I understand, is how top-down TDD works.
(defn start-game
[]
(do-turns))
Now, understandably, I get a huge error; Clojure can't resolve the symbol do-turns. So I thought, maybe if I (declare do-turns) at the top I could keep it from blowing up. No, I get a different error because I'm trying to call an unbound function.
I tried a couple other ways of getting Clojure to recognize do-turns but it seems like the unfinished statement is giving it issues. Am I just using unfinished wrong?
From the Midje docs:
unfinished is similar to Clojure's declare in that it can take multiple arguments and define a var for each one of them. Unlike declare, it binds the var to a function that blows up if called
So when you do (unfinished do-turns) and then call it with (do-turns) an exception is thrown:
Error #'do-turns [the var] has no implementation, but it was called like this:
(do-turns) midje.util.exceptions/user-error (exceptions.clj:13)
You can fix this by removing the (unfinished do-turns) part and provide an implementation of do-turns. E.g.,
(ns clojure-ttt.run-game)
(defn do-turns)
[])
(defn start-game
[]
(do-turns))
and refer it in your test
(ns clojure-ttt.run-game-test
(:require [midje.sweet :refer :all]
[clojure-ttt.run-game :refer [start-game do-turns]])) ; <- do-turns
;; Remove `(unfinished do-turns)` since it is no longer unfinished
(fact "`start-game` returns whatever `do-turns` returns"
(start-game) => ..winner..
(provided
(do-turns) => ..winner..))
;; => returns true
Note that when you have provided an implementation of do-turns, (unfinished do-turns) will throw an exception since an implementation already exists, so it is removed.
Now you have shown that a call to (start-game) returns what (do-turns) returns.

Why Clojure evaluates forms during AOT compilation?

I've set up small project:
project.clj:
(defproject testing-compilation "0.1.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.8.0"]]
;; this is important!
:aot :all)
src/core.clj
(ns testing-compilation.core)
(def x (do
(println "Print during compilation?")
1))
Then when I do lein compile in project directory I'm seeing output from a print:
$ lein compile
Compiling testing-compilation.core
Print during compilation?
My question is: why clojure evaluates top level forms during AOT compilation? Shouldn't they be evaluated at program startup?
For reference, Common Lisp doesn't evaluate forms by default and provides ability to tune this behaviour. Anything similar in Clojure? If nothing, does Clojure documentation explicitly state such behaviour?
UPD: Forms are evaluated at startup as well.
After specifying a main namespace and writing main function that prints Hello, world!, I did this:
$ lein uberjar
Compiling testing-compilation.core
Print during compilation?
Created testing-compilation-0.1.0-SNAPSHOT.jar
Created testing-compilation-0.1.0-SNAPSHOT-standalone.jar
$ java -jar target/testing-compilation-0.1.0-SNAPSHOT-standalone.jar
Print during compilation?
Hello world!
The first part of the AOT process is to find the file containing the main namespace and load it by evaluating every expression from top to bottom.
Some of these expressions will be require expressions that will have the effect of loading other namespaces, which recursively load yet more namespaces.
Other will be defn expressions that will have the effect of firing up the compiler and producing class files. One class file is produced for each function.
Other expressions may do some calculation and then do things that produce class files, so it's important to give them a chance to run. Here's a made up example:
user> (let [precomputed-value (reduce + (range 5))]
(defn funfunfun [x]
(+ x precomputed-value)))
#'user/funfunfun
user> (funfunfun 4)
14
It is possible to design a lisp that would not evaluate top level forms at start or, as you mention, make it optional. In the case of Clojure it was decided to keep a single evaluation strategy across both AOT and "non AOT" loading so programs always run the same regardless of how they are compiled. These are personal design choices made by others so I can't speak to their motivations here.

Why `lein uberjar` evaluates variables defined with `def`?

I'm trying to understand "Lieningen" behaviour when creating an uberjar. Following is the minimal example which reproduces the behaviour:
(ns my-stuff.core
(:gen-class))
(def some-var (throw (Exception. "boom!")))
(defn -main [& args]
(println some-var))
When this is executed with lein run it clearly fails with an Exception. However, I don't understand why executing lein uberjar also fails with an Exception from variable definition? Why executing lein uberjar attempts to evaluate the variable value? Is this speecific to uberjar task or am I missing something more substantial about Clojure or Leiningen?
In order to compile your namespace for the uberjar (if you have AOT turned on), the clojure compiler must load your namespace. This will always invoke all top-level side effects.
The best way to handle this is to never have side effects in top level code (whether inside or outside a def form), and have initialization functions to realize any start-up side effects needed.
A workaround can be to make a small namespace that uses introspection to load the rest of your code at runtime but not while compiling - using a function like this:
(defn -main
[]
(require 'my.primary.ns)
((resolve 'my.primary.ns/start)))
if that namespace is compiled, the jvm can find -main and run it, despite none of your other code being compiled. The runtime require will cause the Clojure compiler to load the rest of your code at runtime only, and resolve is needed so that -main will compile cleanly - it returns the var referenced, which then invokes your function when called.

How do I expect failure in a unit test?

We're writing unit tests for our code in Clojure using clojure.test.
Some of our tests ignore the API and purposely break the code, in order to serve as documentation for latent deficiencies in the code.
However, we want to distinguish between failures of these tests, and failures of normal tests.
We haven't seen any suggestions in the clojure.test documentation -- only (is (thrown? ...)), which of course doesn't do what we need.
Any suggestions? Basically, we're looking for something like (is (not <condition>)), except that the test framework should record an expected failure -- something like this.
I have made tests throw an exception when they 'fail' like this, and then used thrown? to test if the exception arrives as expected. There very well may exist a more elegant way, but this gets the job done.
As #andy said you can rebind report function.
(defmacro should-fail [body]
`(let [report-type# (atom nil)]
(binding [clojure.test/report #(reset! report-type# (:type %))]
~body)
(testing "should fail"
(is (= #report-type# :fail )))))
And use this macro like this:
(should-fail (is (= 1 2)))
That will be successful passing test.
Rebind the report function as documented in clojure.test. From there you can change how the 'failure' is handled and reported on.
A little late to the party, I know, but if you're using Leiningen you could use test selectors to exclude expected failures from the "normal" build. In your project.clj:
:test-selectors {:default #(not :expected-failure %)
:expected-failure :expected-failure}
Then write your test as:
(deftest ^:expected-failure test-with-expected-failure ...)
Calling lein test will run only those tests without the :expected-failure metadata. Calling lein test :expected-failure will run your expected failure tests. Maybe not quite what you were hoping for, but IMHO better than having to use thrown? all over the place. At least this way expected failures are explicitly documented in the code and won't interfere with the build.