Here's my clojure function to try to reproduce the filter function:
(defn singleton? [coll]
(= 1 (count coll)))
(defn my-filter [pred? a-seq]
(if (singleton? a-seq)
(if (pred? (first a-seq))
a-seq)
(if (pred? (first a-seq))
(cons (first a-seq) (my-filter pred? (rest a-seq)))
(my-filter pred? (rest a-seq)))))
And my the midje test is:
(my-filter false? [1 2 3]) => empty? (actual return value is 'nil')
(my-filter even? [1 3 5 7]) => empty? (actual return value is 'nil')
When I run midje, I get the error messages:
FAIL "my-filter" at (recursion.clj:54)
Actual result did not agree with the checking function.
Actual result: nil
Checking function: empty?
FAIL "my-filter" at (recursion.clj:57)
Actual result did not agree with the checking function.
Actual result: nil
Checking function: empty?
I'm pretty confused by this because when I run:
(empty? nil)
in a repl, I get 'true'.
Why is midje failing this test?
Related
Hi everybody I've been recently trying to learn to a new language and I sort of bumped into Clojure which look like a real interesting language because I've never heard about functional programming, even though I had used JavaScript before that kind of leverages it, well I'm gonna stop with the small talk and get into the problem.
I've been working on solving the https://github.com/gigasquid/wonderland-clojure-katas and more specific on the doublets problem. I think I have came with a solution but it send me the error on the title of this post. I have read about this error and it seems that it triggers when you want the compiler expects a function but it doesn't. Here is the full code of my solution to see if you can help me out with this one:
(ns doublets.solver
(:require [clojure.java.io :as io]
[clojure.edn :as edn]
[clojure.set :as set]))
(def words (-> "words.edn"
(io/resource)
(slurp)
(read-string)))
(defn linked-word [word word-list]
(some #(when (= (count (set/difference (into #{} (seq %))
(into #{} (seq word)))) 1) %)
word-list))
(defn doublets [word1 word2]
(let [n (count word1) v (cons word1 (filter #(= (count %) n)
(remove #{word1} words)))]
(tree-seq #(and (linked-word (% 0) %) (not= (% 0) word2))
#(cons (linked-word (% 0) (rest %))
(remove #{(% 0)} (rest %))) v)))
As you can see cons is a function so the error doesn't seem to be the case described above.
I can reproduce the error after downloading the words.edn file and running with (doublets "bank" "loan"). I think the problem is these expressions:
(% 0)
which you have in a few places. I see that you are cons-ing some things, so that may be a clue. What is (% 0) supposed to do?
If you want the first char, just say (first xyz) or something.
I would also break out the anonymous functions #(...) and give them real names.
Update
My guess seems to be correct as this experiment shows:
(cons 1 [2 3]) => (1 2 3)
(class (cons 1 [2 3])) => clojure.lang.Cons
(vec (cons 1 [2 3])) => [1 2 3]
(class (vec (cons 1 [2 3]))) => clojure.lang.PersistentVector
OK, rewrite like:
(defn doublets [word1 word2]
(let [n (count word1)
v (vec (cons word1 (filter #(= (count %) n)
(remove #{word1} words))))]
(tree-seq
#(and
(linked-word (% 0) %)
(not= (% 0) word2))
#(vec (cons (linked-word (% 0) (rest %)))
(remove #{(% 0)} (rest %)))
v)))
new error: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol
And there is the clue we needed!
We are evaluating things as symbols, not strings! The problem is read-string, which is how you read source code, not data like strings. Delete read-string:
(def words (-> "words.edn"
(io/resource)
(slurp)))
We now get a new error on this line:
v (vec (cons word1 (filter #(= (count %) n)
(remove #{word1} words))))]
ERROR in (dotest-line-40) (RT.java:664)
Uncaught exception, not in assertion.
expected: nil
actual: java.lang.UnsupportedOperationException:
count not supported on this type: Character
So your seq has created something like "foo" => [\f \o \o], and you then try to say (count \f). You can't count a single char, only a string.
I'll let you debug it from there.
When I re-implement a macro written in Scheme with Clojure, I get into a trouble.
The macro tries to load pairs of testing data into a all-tests var for later use.
Because the arguments for the macro is variable-length and contains special undefined symbol, i.e. =>, I simply don't know how to parse it like what Scheme syntax-rules does.
Scheme Version:
(define all-tests '())
;;; load tests into all-tests
(define-syntax add-tests-with-string-output
(syntax-rules (=>)
[(_ test-name [expr => output-string] ...)
(set! all-tests
(cons
'(test-name [expr string output-string] ...)
all-tests))]))
(add-tests-with-string-output "integers"
[0 => "0\n"]
[1 => "1\n"]
[-1 => "-1\n"]
[10 => "10\n"]
[-10 => "-10\n"]
[2736 => "2736\n"]
[-2736 => "-2736\n"]
[536870911 => "536870911\n"]
[-536870912 => "-536870912\n"]
)
My current unsuccessful Clojure Version:
(def all-tests (atom '()))
(defmacro add-tests-with-string-output
[test-name & body]
`(loop [bds# (list body)]
(when-not (empty? bds#)
(println (first bds#))
(recur (rest bds#)))))
Ps: I am using println to test my code right now. When it works, I will try to do the parsing and loading work.
The first macro forms a loop and the second one a doseq (so is simpler). Both should behave the same. Also I find it a good idea to extract as much logic out of macros into auxiliary functions. Functions are easier to debug, test and write. If the macro were a bit more complicated I might have left even less logic in it.
(def all-tests (atom '()))
(defn add-test [test-name expr output-string]
(swap! all-tests #(cons (list test-name [expr output-string]) %)))
(defmacro add-tests-with-string-output
[test-name & body]
;`(loop [bds# '(~#body)]
`(loop [bds# '~body] ; edit
(when-not (empty? bds#)
(let [bd# (first bds#)
expr# (first bd#)
output-string# (last bd#)]
(add-test ~test-name expr# output-string#)
(recur (rest bds#))
))))
(defmacro add-tests-with-string-output2
[test-name & body]
;`(doseq [bd# '(~#body)]
`(doseq [bd# '~body] ; edit
(let [expr# (first bd#)
output-string# (last bd#)]
(add-test ~test-name expr# output-string#))))
user=> (add-tests-with-string-output "test1" [0 => "0\n"] [1 => "1\n"])
nil
user=> (add-tests-with-string-output2 "test2" [0 => "0\n"] [1 => "1\n"])
nil
user=> #all-tests
(("test2" [1 "1\n"]) ("test2" [0 "0\n"]) ("test1" [1 "1\n"]) ("test1" [0 "0\n"]))
After trials and errors, finally I figure out how to solve it.
First use Destructuring to tackle the arguments of variable-length;
later do not use Syntax-Quoting, i.e. backquote `, inside the macro, because if so, once you need to unquote ~ the argument, i.e. body, you will get error msg like this due to the special symbol =>:
CompilerException java.lang.RuntimeException: Unable to resolve
symbol: => in this context
Below is my solution.
If you get better one, or you know the reason why Syntax-Quote and Unquote go wrong, please let me know.
;;; load tests into all-tests
(def all-tests (atom '()))
(defmacro add-tests-with-string-output
[test-name & body]
(loop [bds body, tests '()]
(if (empty? bds)
(do
(swap! all-tests #(cons (cons test-name tests) %))
nil)
(let [pair (first bds),
input (first pair)
output (last pair)]
(recur (rest bds) (cons (list input ''string output) tests))))))
Many times when I try to write some function I get exception. That is normal. In Java you can find place and reason why exception occures but in clojure exception texts just make me crazy. Is there some tips how to read exceptions in clojure and how to find where in code exception happens and why?
For example I will take some code:
(do
(list?)
(list? [])
(list? '(1 2 3))
(list? (defn f [] (do ())))
(list? "a"))
when I call this function in REPL I will get
java.lang.IllegalArgumentException: Wrong number of args (0) passed to: core$list-QMARK- (NO_SOURCE_FILE:46)
which do not help me much to find the problem in second line. In little more complicated code it will give almost no information. (Of course it tells look at list? in some there is wrong number of arguments.) Is it wrong that I try to write code in REPL? How to read exception mesages in REPL? Is there way how to get better information about exceptions in REPL?
You can use clojure.stacktrace: http://richhickey.github.com/clojure/clojure.stacktrace-api.html
Usage:
(use 'clojure.stacktrace)
(/ 1 0)
(e)
Output:
java.lang.ArithmeticException: Divide by zero
at clojure.lang.Numbers.divide (Numbers.java:156)
clojure.lang.Numbers.divide (Numbers.java:3691)
user$eval954.invoke (NO_SOURCE_FILE:1)
clojure.lang.Compiler.eval (Compiler.java:6511)
clojure.lang.Compiler.eval (Compiler.java:6477)
clojure.core$eval.invoke (core.clj:2797)
clojure.main$repl$read_eval_print__6405.invoke (main.clj:245)
clojure.main$repl$fn__6410.invoke (main.clj:266)
nil
Acquire org.clojure/tools.trace.
user=> (use 'clojure.tools.trace)
Let's try a dotrace (changed up the order to make things more interesting):
user=> (dotrace [list?]
#_=> (do
#_=> (list? [])
#_=> (list? '(1 2 3))
#_=> (list?)
#_=> (list? (defn f [] (do ())))
#_=> (list? "a"))
#_=> )
IllegalStateException Can't dynamically bind non-dynamic var: clojure.core/list?
clojure.lang.Var.pushThreadBindings (Var.java:353)
Hmm...
user=> (.setDynamic #'list?)
#'clojure.core/list?
Let's try that again:
user=> (dotrace [list?]
#_=> (do
#_=> (list? [])
#_=> (list? '(1 2 3))
#_=> (list?)
#_=> (list? (defn f [] (do ())))
#_=> (list? "a")))
TRACE t1216: (list? [])
TRACE t1216: => false
TRACE t1217: (list? (1 2 3))
TRACE t1217: => true
TRACE t1218: (list?)
ArityException Wrong number of args (0) passed to: core$list-QMARK-
clojure.lang.AFn.throwArity (AFn.java:437)
Aha! Made it to (list?) before the exception.
I encountered the StackOverflowError for the following code:
(defn recursive-reverse
([coll] (recursive-reverse [coll nil]))
([coll acc]
(if (= coll '()) acc
(recur (rest coll) (cons (first coll) acc)))))
though using loop would make it work:
(defn recursive-reverse [lst]
(loop [coll lst acc nil]
(if (= coll '()) acc
(recur (rest coll) (cons (first coll) acc)))))
What goes wrong with the prior code without loop?
Your bug is here:
([coll] (recursive-reverse [coll nil]))
You're calling recursive-reverse with one argument (a vector). This calls the same argument list of the function, so it does it recursively and creates a stack frame every time.
Change it to:
([coll] (recursive-reverse coll nil))
and you should be right.
(Also, separate issue, but I would generally do checking for nil rather than '() and using next rather than rest. I don't think it has any real advantage in terms of performance or anything, but it seems cleaner to me.)
This worked for me:
(defn recursive-reverse
([coll] (recursive-reverse coll nil))
([coll acc]
(if (= coll '()) acc
(recur (rest coll) (cons (first coll) acc)))))
You passed the arguments to recursive-reverse inside a couple of unnecessary brackets, that's all.
Are there non-macro versions of and and or in Clojure?
Update: In this case I don't care about the short circuiting.
or
The function some "Returns the first logical true value of (pred x) for any x in coll, else nil."
So you could use (some identity coll) for or. Note that its behaviour will differ from or when the last value is false: it will return nil where or would return false.
and
If you don't need to know the value of the last form in the coll vector, you can use (every? identity coll) for and. This will differ from the behaviour of the and macro in that it returns true if all of its arguments are truthy. See larsmans' answer if you need the result of the last form.
Let land stand for "logical and", then they're trivial to define:
(defn land
([] true)
([x & xs] (and x (apply land xs))))
Or, slightly closer to the standard and behavior:
(defn land
([] true)
([x] x)
([x & xs] (and x (apply land xs))))
And similarly for or.
This actually came up as a topic on clojure-dev recently. Rich Hickey ultimately concluded they should be added to core for 1.3 as every-pred and any-pred (logged as CLJ-729). I think further discussions there have led them to now be called every-pred (the and variant) and some-fn (the or variant). The final version was just recently committed to master.
If you mean functions: no, and they cannot be. The reason is that function forms always evaluate all their arguments before applying the function to their value. You do not want that here.
Most cases where you want this there is a more idiomatic way to do it, but just an exercise, it is possible to defer evaluation by thunking. Thunk your expressions and give them to logical operators that evaluate the the thunk when needed, using the standard and/or:
(defn &&* [& fns]
(cond (= 1 (count fns)) ((first fns))
:otherwise
(and ((first fns)) (apply &&* (next fns)))))
(defn ||* [& fns]
(cond (= 1 (count fns)) ((first fns))
:otherwise
(or ((first fns)) (apply ||* (next fns)))))
Example use:
(map
(partial apply &&*)
(map (partial map constantly) ;; thunk all of these values
[["yes" "no"]
[false true]
[true "something"]
[true "something" "false"]]))
("no" false "something" "false")
Another Example:
(defmacro thunks
"convert expressions into thunks to prevent advance evaluation"
[& exprs]
(let [fns# (map (fn [e] `(fn [] ~e)) exprs)]
(cons 'vector fns#)))
(apply ||* (thunks (+ 1 2) false (* 1 5)))
3
(apply &&* (thunks (+ 1 2) false (* 1 5)))
false
(apply &&* (thunks (+ 1 2) (* 1 5)))
5