ClassCastException java.lang.Boolean cannot be cast to clojure.lang.IFn - clojure

(defn is-member? [a lst]
((cond
(empty? lst) false
(= a (first lst)) true
:else (is-member? a (rest lst))
)))
(is-member? :b '(:a :b :c))
When I execute the above code I get error
ClassCastException java.lang.Boolean cannot be cast to clojure.lang.IFn user/is-member? (NO_SOURCE_FILE:28)
Why?
I understand that if an expression is enclosed in parentheses then that means it will be evaluated as a function..

You got the cond expression in double parentheses. That causes the final result of cond (true or false) to be called as a function. Fix that and it works.
=> (defn is-member?
[a lst]
(cond
(empty? lst) false
(= a (first lst)) true
:else (is-member? a (rest lst))))
#'user/is-member?
=> (is-member? :b '(:a :b :c))
true
The most idiomatic way to do this in Clojure, by the way, is using some.
=> (some #{:b} [:a :b :c])
:b
This returns the actual first value, but because of Clojure's truthiness it can be used in conditionals in much the same way as true and false.

As I discovered, even if the cond expression is in single parentheses, you'll get the same ClassCastException if you wrap each conditional test-expression pair in parentheses.
;; INCORRECT
(defn is-member?
[a lst]
(cond
((empty? lst) false)
((= a (first lst)) true)
(:else (is-member? a (rest lst)))))
;; CORRECT
(defn is-member?
[a lst]
(cond
(empty? lst) false
(= a (first lst)) true
:else (is-member? a (rest lst))))

Related

Clojure functions which perform symbolic simplification using 'and'

I am new to Clojure and I'm learning how to write a program that can simplify logical expressions (just 'and' for now to figure out how things work first). For example:
(and-simplify '(and true)) => true
(and-simplify '(and x true)) => x
(and-simplify '(and true false x)) => false
(and-simplify '(and x y z true)) => (and x y z)
I already knew how to simplify two arguments, that everything I can do right now is:
(defn and-simplify []
(def x (and true false))
println x)
(and-simplify)
I've read this post and tried to modify my code a little bit but it doesn't seem to get me anywhere:
(defn and-simplify [&expr]
(def (and &expr))
)
What is the correct way that I should have done?
Here's my take on it.
(defn simplify-and
[[op & forms]]
(let [known-falsy? #(or (false? %) (nil? %))
known-truthy? #(and (not (symbol? %))
(not (seq? %))
(not (known-falsy? %)))
falsy-forms (filter known-falsy? forms)
unknown-forms (remove known-truthy? forms)]
(if (seq falsy-forms)
(first falsy-forms)
(case (count unknown-forms)
0 true
1 (first unknown-forms)
(cons op unknown-forms)))))
(comment (simplify-and `(and true 1 2 a)))
However, we can write a more generic simplify that uses multimethods to simplify lists, so that we can add more optimisations without modifying existing code. Here's that, with optimisations for and, or and + from clojure.core. This simplify only optimises lists based on namespace qualified names.
Check out the examples in the comment form. Hope it makes sense.
(defn- known-falsy? [form]
(or (false? form) (nil? form)))
(defn- known-truthy? [form]
(and (not (symbol? form))
(not (seq? form))
(not (known-falsy? form))))
(declare simplify)
(defmulti simplify-list first)
(defmethod simplify-list :default [form] form)
(defmethod simplify-list 'clojure.core/and
[[op & forms]]
(let [forms (mapv simplify forms)
falsy-forms (filter known-falsy? forms)
unknown-forms (remove known-truthy? forms)]
(if (seq falsy-forms)
(first falsy-forms)
(case (count unknown-forms)
0 true
1 (first unknown-forms)
(cons op unknown-forms)))))
(defmethod simplify-list 'clojure.core/or
[[op & forms]]
(let [forms (mapv simplify forms)
truthy-forms (filter known-truthy? forms)
unknown-forms (remove known-falsy? forms)]
(if (seq truthy-forms)
(first truthy-forms)
(case (count unknown-forms)
0 nil
1 (first unknown-forms)
(cons op unknown-forms)))))
(defmethod simplify-list 'clojure.core/+
[[op & forms]]
(let [{nums true non-nums false} (group-by number? (mapv simplify forms))
sum (apply + nums)]
(if (seq non-nums)
(cons op (cons sum non-nums))
sum)))
(defn simplify
"takes a Clojure form with resolved symbols and performs
peephole optimisations on it"
[form]
(cond (set? form) (into #{} (map simplify) form)
(vector? form) (mapv simplify form)
(map? form) (reduce-kv (fn [m k v] (assoc m (simplify k) (simplify v)))
{} form)
(seq? form) (simplify-list form)
:else form))
(comment
(simplify `(+ 1 2))
(simplify `(foo 1 2))
(simplify `(and true (+ 1 2 3 4 5 foo)))
(simplify `(or false x))
(simplify `(or false x nil y))
(simplify `(or false x (and y nil z) (+ 1 2)))
)

How to fix recursive search through list

I'm currently trying to learn Clojure. But I am having trouble creating a function that recursively searches through each element of the list and returns the number of "a"'s present in the list.
I have already figured out how to do it iteratively, but I am having trouble doing it recursively. I have tried changing "seq" with "empty?" but that hasn't worked either.
(defn recursive-a [& lst]
(if (seq lst)
(if (= (first lst) "a")
(+ 1 (recursive-a (pop (lst))))
(+ 0 (recursive-a (pop (lst)))))
0))
Welcome to stack overflow community.
You code is fine, except that you made a few minor mistakes.
Firstly, there is one extra pair of braces around your lst parameter that you forward to recursive function. In LISP languages, braces mean evaluation of function. So, first you should remove those.
Second thing is the & parameter syntactic sugar. You do not want to use that until you are certain how it affects your code.
With these changes, the code is as follows:
(defn recursive-a [lst]
(if (seq lst)
(if (= (first lst) "a")
(+ 1 (recursive-a (pop lst)))
(+ 0 (recursive-a (pop lst))))
0))
(recursive-a (list "a" "b" "c"))
You can run it in a web environment: https://repl.it/languages/clojure
Welcome to Stack Overflow.
By invoking recursive-a explicitly the original implementation consumes stack with each recursion. If a sufficiently large list is provided as input this function will eventually exhaust the stack and crash. There are a several ways to work around this.
One of the classic Lisp-y methods for handling situations such as this is to provide a second implementation of the function which passes the running count as an input argument to the "inner" function:
(defn recursive-a-inner [cnt lst]
(cond
(seq lst) (cond
(= (first lst) "a") (recur (inc cnt) (rest lst))
:else (recur cnt (rest lst)))
:else cnt))
(defn recursive-a [& lst]
(recursive-a-inner 0 lst))
By doing this the "inner" version allows the recursion to be pushed into tail position so that Clojure's recur keyword can be used. It's not quite as clean an implementation as the original but it has the advantage that it won't blow up the stack.
Another method for handling this is to use Clojure's loop-ing, which allows recursion within the body of a function. The result is much the same as the "inner" function above:
(defn recursive-a [& lp]
(loop [cnt 0
lst lp]
(cond
(seq lst) (cond
(= (first lst) "a") (recur (inc cnt) (rest lst))
:else (recur cnt (rest lst)))
:else cnt)))
And if we drop the requirement for explicit recursion we can make this a bit simpler:
(defn not-recursive-a [& lst]
(apply + (map #(if (= % "a") 1 0) lst)))
Best of luck.
In the spirit of learning:
You can use & or not. Both are fine. The difference is how you would then call your function, and you would have to remember to use apply when recurring.
Also, simply use first and rest. They are both safe and will work on both nil and empty lists, returning nil and empty list respectively:
(first []) ;; -> nil
(first nil) ;; -> nil
(rest []) ;; -> ()
(rest nil) ;; -> ()
So here is how I would re-work your idea:
;; With '&'
(defn count-a [& lst]
(if-let [a (first lst)]
(+ (if (= a "a") 1 0)
(apply count-a (rest lst))) ;; use 'apply' here
0))
;; call with variable args, *not* a list
(count-a "a" "b" "a" "c")
;; Without '&'
(defn count-a [lst]
(if-let [a (first lst)]
(+ (if (= a "a") 1 0)
(count-a (rest lst)))
0))
;; call with a single arg: a vector (could be a list or other )
(count-a ["a" "b" "a" "c"])
However, these are not safe, because they don't use tail-recursion, and so if your list is large, you will blow your stack!
So, we use recur. But if you don't want to define an additional "helper" function, you can instead use loop as the "recur" target:
;; With '&'
(defn count-a [& lst]
(loop [c 0 lst lst] ;; 'recur' will loop back to this point
(if-let [a (first lst)]
(recur (if (= a "a") (inc c) c) (rest lst))
c)))
(count-a "a" "b" "a" "c")
;; Without '&'
(defn count-a [lst]
(loop [c 0 lst lst]
(if-let [a (first lst)]
(recur (if (= a "a") (inc c) c) (rest lst))
c)))
(count-a ["a" "b" "a" "c"])
All that being said, this is the one I also would use:
;; With '&'
(defn count-a [& lst]
(count (filter #(= % "a") lst)))
(count-a "a" "b" "a" "c")
;; Without '&'
(defn count-a [lst]
(count (filter #(= % "a") lst)))
(count-a ["a" "b" "a" "c"])

Why does a StackOverflowError occur only when function doesn't use sequence destructing?

The following code was run on the 4closure site for problem 19.
The function I was writing was supposed to return the last element in a sequence.
A java.lang.StackOverflowError occurred for this definition:
(fn my-last [lst]
(if (rest lst)
(my-last (rest lst))
(first lst)))
But when I ran the following definition it worked fine:
(fn my-last [[x & xs]]
(if xs
(my-last xs)
x))
The only difference in the two blocks above seems to be the destructive sequence binding use of destructuring in the parameter list.
So how come the first definition throws an error?
And are there any differences between the two functions that I am missing?
Edit: fixed typo in first function definition
Here is the answer:
(rest [1 2 3]) => (2 3)
(rest [3]) => ()
(next [3]) => nil
Using rest returns the empty sequence (), which evaluates to true in your test. Using next returns nil when there are no more items. Since Clojure considers nil the same as false, this will make it work.
Since many people get tripped up on this point, I would prefer a more explicit test, such as this:
(if-not (empty? ...))
or similar.
Update:
Here is how I would write it. The testing stuff is from the Tupelo library.
(ns tst.demo.core
(:use tupelo.test)
(:require
[tupelo.core :as t]))
(defn get-last
[items]
(when (empty? items)
(throw (IllegalArgumentException. "get-last: items must not be empty")))
(let [others (rest items)]
(if (empty? others)
(first items)
(get-last others))))
(dotest
(throws? (get-last []))
(is= 1 (get-last [1]))
(is= 2 (get-last [1 2]))
(is= 3 (get-last [1 2 3])))
Some people will insist that the above example is not "pure" enough, but I think explicit clarity beats out implicit behavior every time.
Update #2
When in doubt, ask the code what it is doing:
(defn my-last
[[x & xs]]
(t/spyx {:x x :xs xs})
(if xs
(t/spyx (my-last xs))
(t/spyx x)))
(dotest
(t/spyx (my-last [1 2 3])))
results with:
{:x x, :xs xs} => {:x 1, :xs (2 3)}
{:x x, :xs xs} => {:x 2, :xs (3)}
{:x x, :xs xs} => {:x 3, :xs nil}
x => 3
(my-last xs) => 3
(my-last xs) => 3
(my-last [1 2 3]) => 3
And there you have your answer.
TL;DR answer:
The first version was creating an infinite loop because that if statement will never be false since (rest [x]) and (rest []) return a truthy value
Pro Tip: Here are some fun ways to break on an empty sequence:
empty?
seq
(zero? (count coll))
The most idiomatic way is using seq with destructuring:
(fn my-last [[x & xs]]
(if (seq xs)
(my-last xs)
x))
but you could have also wrapped your original solution in seq and it would have worked:
(fn my-last [lst]
(if (seq (rest lst))
(my-last (rest lst))
(first lst)))
(seq (rest lst)) will return nil which is a falsey value when lst only has one element which is what you were checking for.
A side note, another way you could have solved this is to
! get the first element of the reversed collection since for problem 19 only last is banned
! (comp reverse first)

Calling a function with (rest [1[2]]) in Clojure as an argument is different from calling with argument ([2])

So I've been solving a 4clojure problem, where I need to implement the function flatten and I am trying to debug my solution, which is:
(defn fn1 [x]
(if (not (or (list? x) (vector? x)))
(list x)
(if (empty? (rest x))
(if (not (or (list? x) (vector? x)))
(list x)
(fn1 (first x))
)
(if (or (list? (first x)) (vector? (first x)))
( concat (fn1 (first x)) (fn1 (rest x)) )
( concat (fn1 (list (first x))) (fn1 (rest x)) )
)
)
)
)
While trying to debug, I encountered the following behaviour:
user=> (fn1 (rest [1[2]]))
(([2]))
user=> (rest [1[2]])
([2])
user=> (fn1 '([2]))
(2)
What is the reason behind that and how can I get around it?
I haven't looked to much in your code, but it looks like because
> (type (rest [1 2]))
clojure.lang.PersistentVector$ChunkedSeq
> (vector? (rest [1 2]))
false
> (list? (rest [1 2]))
false
> (seq? (rest [1 2]))
true
So if rest of list is a list, rest of vector is not a list or vector,
but ChunkedSeq
Although they render the same at the REPL, (rest [1 [2]]) and '([2]) have different types:
(type (rest [1 [2]])) ; clojure.lang.PersistentVector$ChunkedSeq
(type '([2])) ; clojure.lang.PersistentList
The former answers false to list? whereas the latter answers true.

CompilerException java.lang.RuntimeException: Unable to resolve symbol: invert-helper in this context

I'm pretty new to closure and I don't understand why I'm getting this error message at runtime. Here is my code:
(defn invert [lst]
(if (empty? lst)
()
(cons (invert-helper lst) (invert (rest lst)))))
(defn invert-helper [lst]
(list (nth lst 1) (first lst)))
This should fix the problem:
(defn invert-helper [lst]
(list (nth lst 1) (first lst)))
(defn invert [lst]
(if (empty? lst)
()
(cons (invert-helper lst) (invert (rest lst)))))
That is: the invert-helper function must be defined before its first use in invert.
Another option, apart from defining all the functions before using them, may be declaring invert-helper before invert:
(declare invert-helper)
(defn invert [lst]
(if (empty? lst)
()
(cons (invert-helper lst) (invert (rest lst)))))
(defn invert-helper [lst]
(list (nth lst 1) (first lst)))
You're also calling (nth lst 1) where lst may have only one element - this will throw an exception.