I am trying co join two list using map and logical function "and"
(map and '(true false true) '(0 1 2))
I expect to see
(0 false 2)
Instead of that
CompilerException java.lang.RuntimeException: Can't take value of a macro:
#'clojure.core/and, compiling:(NO_SOURCE_PATH:274:1)
occures.
How can I fix it?
You can wrap the "and" macro into a function
(map #(and % %2) '(true false true) '(0 1 2))
Result:(0 false 2)
The map function don't let you to use macros as first argument, so this is an easy trick to solve the problem
accepted answer is definitely solid, I just wanted to give you an example of converting a macro to a function (mostly for entertaining/learning purposes):
(defmacro to-fun [macro] ;; converting a macro to a function
`#(eval (cons '~macro %&))) ;; e.g. "eval"uated at run time vs. compile time,
;; and hence can be composed
now we can just wrap a(ny) macro with it:
(map (to-fun and) [true false true] [0 1 2])
(0 false 2)
or:
(map (to-fun or) [true false true] [0 1 2])
(true 1 true)
Related
I am doing is-prime? function that should return true if n is prime and false otherwise, it also should check to see if n is 1 or 2 and respond accordingly; if not, it should call no-divisors function. At the moment I get this output :
Can anyone see what's wrong, would be much appreciated
expected result is false,current false
expected result is true,current true
expected result is true,current false
expected result is false,current false
expected result is true,current false
no-divisors?
(->> (range 2 n)
(filter #(Divides % n))
empty? ))
(println (no-divisors? 4))
is-prime?
(defn is-prime? [n]
(and (< 1 n)
(not-any? (filter #(no-divisors? % n))
(range 2 n))))
(println "expected result is false,current"( is-prime? 1))
(println "expected result is true,current"( is-prime? 2))
(println "expected result is true,current" ( is-prime? 3))
(println "expected result is false,current"( is-prime? 4))
(println "expected result is true,current"( is-prime? 101))
If you format your code per Clojure conventions, it's pretty clear what the problem is:
(defn is-prime? [n]
(and (< 1 n)
(not-any? (filter #(no-divisors? % n))
(range 2 n))))
You're calling filter with a single argument which with return a transducer. Your call to not-any? then tries to treat that transducer as a predicate and since a transducer, given a single argument, returns a function -- and a function is "truthy" (not nil or false) then not-any? will return false per its definition.
The reason it returns true for 2 is that (range 2 2) is an empty sequence and not-any? returns true for an empty sequence without calling the predicate.
Some suggestions:
Several people have asked you for complete, well-formatted code. Provide
it. It will help you think clearly.
Use integer? and < to make sure you are testing a possible prime.
A prime is a number with no proper factors. Define it as such. You
are doing the work twice - Russian doll style.
It is easier to test your function on a range of possibles. I used (filter prime? (range -20 20)), yielding (2 3 5 7 11 13 17 19).
Name the function prime?. That's the Clojure convention. The initial is- is redundant. This may seem nit-picking, but simpler is clearer.
Best of luck!
Is Clojure's logical and different from the normal logical and (&&)? Why does this yield true
((and odd? #(> 10 %)) 6)
Doesn't and need 2 true statements to return true?
and doesn't necessarily return true. It actually returns false or nil if any of the given elements is false or nil. If none of them are, then it returns the very last element (it does not return true).
In your case the and returns the function #(> 10 %) (and nothing else) which is then applied to 6 which yields true. This is because both functions are neither nil nor false.
This is how the steps would work:
((and odd? #(> 10 %)) 6)
(#(> 10 %) 6)
;; => true
What you're looking for is to compose predicate functions:
((every-pred odd? #(> 10 %)) 6) ;; => false
FYI: There is also it's complement "or": some-fn.
I want to write a macro to accept a vector params
(defmacro eval-verify [body]
`(cond
~#body
:default nil))
it work in this case
(eval-verify [true 1 false 2])
it return 1,and i run
(macroexpand-1 '(eval-verify [true 1 false 2]))
it return
(clojure.core/cond true 1 false 2 :default nil)
it seems ok,but when i def a vector
(def a [true 1 false 2])
and run
(eval-verify a)
it is error
IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Symbol
how to write a macro can accept argument which is symbol,or write functoin can do the same things.
Macro arguments are passed as unevaluated symbols. Therefore when you invoke (eval-verify a) the symbol a is the value of the body argument passed to eval-verify and not [true 1 false 2]. Since unquote-splice (~#) expects a Seq and it finds a symbol (a), you receive the IllegalArgumentException.
You would either need to invoke eval-verify using the form (eval-verify [true 1 false 2]) or you would need to use a plain function.
You can use the following function instead of a macro:
(defn eval-verify [coll]
(loop [[f v :as c] coll]
(cond
(and (ifn? f) (f)) v
(and (not (ifn? f)) f) v
:else (if (seq c) (recur (drop 2 c)) nil))))
I have this Clojure code:
(defn apply-all-to-arg [& s]
(let [arg (first s)
exprs (rest s)]
(for [condition exprs] (condition arg))))
(defn true-to-all? [& s]
(every? true? (apply-all-to-arg s)))
This is test code:
(apply-all-to-arg 2 integer? odd? even?)
=> (true false true)
(every? true? (apply-all-to-arg 2 integer? odd? even?)
=> false
(true-to-all? 2 integer? odd? even?)
=> true
My question is:
Why does the function true-to-all? return true (it must have returned false instead)
true-to-all? calls apply-all-to-arg with the single argument s. So you're not calling (every? true? (apply-all-to-arg 2 integer? odd? even?), but rather:
(every? true? (apply-all-to-arg (list 2 integer? odd? even?))
So in apply-all-to-arg the value of arg will be that list and the value of exprs will be the empty list. Since every? will be true for the empty list no matter what the condition is, you'll get back true.
To fix this you can either change apply-all-to-arg, so that it accepts a list instead of a variable number of arguments, or you can change true-to-all?, so that it passes the contents of s as multiple arguments rather than a single list (by using apply).
The default Clojure function that creates a function that applies several functions to one argument in parallel is juxt:
=> ((juxt integer? odd? even?) 2)
[true false true]
=> (every? true? ((juxt integer? odd? even?) 2))
false
=> (defn true-to-all? [a & fns]
(every? true? ((apply juxt fns) a)))
=> (true-to-all? 2 integer? odd? even?)
false
If the functions you combine with juxt all take multiple arguments it works as well
=> ((juxt + - / *) 6 3)
[9 3 2 18]
Because when you call true-to-all?, the parameter s is a list, so you are effectively calling (apply-all-to-arg '(2 integer? odd? even?))
Try defining true-to-all? like this:
(defn true-to-all? [& s]
(every? true? (apply apply-all-to-arg s))
You can also defined your function like below to make it more clear.
(defn apply-all-to-arg [v & fns]
(map #(% v) fns))
As this makes the function definition clear that it takes a value and optional functions to apply to that value.
Look at the function below. I want to pass a vector of factors and test if any of the elements in the vector is a factor of x. How do I do that?
(defn multiple?
"Takes a seq of factors, and returns true if x is multiple of any factor."
([x & factors] (for [e m] ))
([x factor] (= 0 (rem x factor))))
You could try using some and map:
(defn multiple? [x & factors]
(some zero? (map #(rem x %) factors)))
Also some returns nil if all tests fail, if you need it to actually return false, you could put a true? in there:
(defn multiple? [x & factors]
(true? (some zero? (map #(rem x %) factors))))
Note that some short-circuits and map is lazy, so multiple? stops as soon as a match is found. e.g. the following code tests against the sequence 1,2,3,4,....
=> (apply multiple? 10 (map inc (range)))
true
Obviously this computation can only terminate if multiple? doesn't test against every number in the sequence.
You can solve it only using some.
=> (defn multiple? [x factors]
(some #(zero? (rem x %)) factors))
#'user/multiple?
=> (= true (multiple? 10 [3 4]))
false
=> (= true (multiple? 10 [3 4 5 6]))
true
some will stop at the first factor.
Try this, using explicit tail recursion:
(defn multiple? [x factors]
"if any of the elements in the vector is a factor of x"
(loop [factors factors]
(cond (empty? factors) false
(zero? (rem x (first factors))) true
:else (recur (rest factors)))))
The advantages of the above solution include: it will stop as soon as it finds if any of the elements in the vector is a factor of x, without iterating over the whole vector; it's efficient and runs in constant space thanks to the use of tail recursion; and it returns directly a boolean result, no need to consider the case of returning nil. Use it like this:
(multiple? 10 [3 4])
=> false
(multiple? 10 [3 4 5 6])
=> true
If you want to obviate the need to explicitly pass a vector (for calling the procedure like this: (multiple? 10 3 4 5 6))) then simply add a & to the parameter list, just like it was in the question.
A more Clojurian way is to write a more general-purpose function: instead of answering true/false question it would return all factors of x. And because sequences are lazy it is almost as efficient if you want to find out if it's empty or not.
(defn factors [x & fs]
(for [f fs :when (zero? (rem x f))] f))
(factors 5 2 3 4)
=> ()
(factors 6 2 3 4)
=> (2 3)
then you can answer your original question by simply using empty?:
(empty? (factors 5 2 3 4))
=> true
(empty? (factors 6 2 3 4))
=> false