Dereferencing an atom in a 'case' expression - clojure

This returns true:
(def a (atom 1))
(case #a 1 true false)
but this returns false:
(def a (atom 1))
(case 1 #a true false)
Shouldn't the 2nd expression return true?
Answer:
Explanation by #Carcigenicate: "every second argument to case need to be a compile-time literal".
#a is not, so the case expression must be replaced with a if:
(def a (atom 1))
(if (= 1 #a) true false))

Related

Cannot pass list as argument to function

I have a substitute function that will take in an expression such as (or false x y) and a binding map such as '{x false, y true} and will return the list with the appropriate substitutions. The result is in l and displayed. How might I pass l into another function to do some other processing? The definition for the function I'm passing to looks like this:
(defn f [expression]
)
I have tried passing l as a parameter when calling f, but I get the following error:
IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Symbol clojure.lang.RT.seqFrom (RT.java:550)
Here is my substitute function:
(defn deep-substitute [m l]
(map (fn [i]
(if (seq? i)
(deep-substitute m i)
(m i i)))
l
(f 'l)))
My new function fully works the way I expect it to when calling it with an unevaluated list, but not when I pass it an unevaluated list.
The job of deep-substitute is to fill in a template form and return it. The problem gets harder if you try to make deep-substitute also responsible for doing the next step in the transformations as well. Perhaps let it return the value, then pass that value on to another transform function after it's returned.
Here's an annotated working example:
user> (defn deep-substitute [m l]
(map (fn [i]
(if (seq? i) ;; if this is a sequence,
(deep-substitute m i) ;; finish the sequence and include the result here
(get m i i))) ;; otherwise get the new value from the map, if found
l)) ;; if it's not found, us the value unchanged.
#'user/deep-substitute
then test it on your example:
user> (deep-substitute '{x false, y true} '(or false x y))
(or false false true)
and a more nested example:
user> (deep-substitute '{x false, y true} '(or false (and x (or y x)) y))
(or false (and false (or true false)) true)
a common next step is to wrap that in a macro so it can modify forms before they are evaluated, then evaluate that newly created from to find out what value it becomes:
user> (defmacro dsub [m l]
(deep-substitute m l))
#'user/dsub
and test it
user> (dsub {x false, y true} (or false (and x (or y x)) y))
true
user> (dsub {x false, y true} (or false x))
false
or pass the resulting form (unevaluated) into another function by nesting it:
user> (defn f [expression]
(reverse expression))
#'user/f
user> (f (deep-substitute '{x false, y true} '(or false (and x (or y x)) y)))
(true (and false (or true false)) false or)
A common pattern is to use the threading macros -> ->> etc. to pass the result from transform to transform until the final result is made by composing many simple operations:
user> (->> '(or false (and x (or y x)) y)
(deep-substitute '{x false, y true})
f
(deep-substitute '{false, 41 true 42}))
(42 (and 41 (or 42 41)) 41 or)
first try with the basic approach of the passing list as an argument to the function. You can refer below example
(defn passlist [a]
(println a))
(passlist '(1 2 3))
Output will:
#'user/passlist
(1 2 3)

Logical AND in Clojure

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.

how to write a macro can accept argument which is symbol

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))))

Clojure - why is the "do" statement necessary for grouping?

I understand that a do block will execute statements in sequence and return the value of the last one. I'd thought that if I didn't need the return value the do would be unnecessary. Not considering the return value, then, I don't understand the different behavior of these 2 functions:
with "do":
(defn x []
(if true
(do (println "a") (println "b"))))
=> (x)
a
b
nil
without "do":
(defn x []
(if true
((println "a") (println "b"))))
=> (x)
a
b
NullPointerException user/x (NO_SOURCE_FILE:3)
What is the cause of the NullPointer in the second example?
Because
(function argument)
...is function-call syntax,
((println "a") (println "b"))
...expects (println "a") to return a function, which it can call with the result of (println "b") passed as its first argument.
Instead, (println "a") has no return value (returns nil, aka null), and trying to call this null value as a function gives you your NullPointerException.
By the way, the idiomatic thing to do here would be to replace your if with a when, which will expand to implicitly include a do:
(defn x []
(when true
(println "a")
(println "b")))

Mapping logical function

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)