how to write a macro can accept argument which is symbol - clojure

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

Related

I don't understand the (doc fn)...it says I can name a function, but I can't invoke it by its name?

I'm new to Clojure and am grasping to understand the concepts. The REPL helpfully lets me get docs of "stuff". So I want to define a function...
clojure-noob.core> (doc fn)
-------------------------
clojure.core/fn
(fn name? [params*] exprs*)
(fn name? ([params*] exprs*) +)
Special Form
...
name => symbol
...and the doc suggests that I can name my function. The REPL accepts my function, but I can't invoke it, "Unable to resolve symbol.."...
clojure-noob.core> (fn add-pair [a b] (+ a b))
#<core$eval3364$add_pair__3365 clojure_noob.core$eval3364$add_pair__3365#6fb5a33b>
clojure-noob.core> (add-pair 1 2)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: add-pair in this context, compiling:(/private/var/folders/1g/fnytl2x93sx6hp2f1rsf4h1r5xtqv_/T/form-init6828995349142227131.clj:1:1)
clojure-noob.core>
Leaving off the name and building a proper def of the fn does get the job done as does leveraging the defn macro thing...
clojure-noob.core> (def another-add-pair (fn [a b] (+ a b)))
clojure-noob.core> (another-add-pair 1 2)
3
clojure-noob.core> (defn yet-another-add-pair [a b] (+ a b))
#'clojure-noob.core/yet-another-add-pair
clojure-noob.core> (yet-another-add-pair 3 4)
7
There is obviously something I don't understand about the output of (doc fn). In particluar, what is the name? there and what can you do with it? I am as much trying to learn how to read the docs as well as understand the fn special form. Thanks.
calling (fn add-pair [a b] (+ a b)) from the REPL builds an instance of that function and then prints it to the screen. After that it goes away and is not saved anywhere. This is why you can't get it's docs using the doc function. The name parameter in the fn literal is often used for making recursive calls and does not mean that it will be saved by that name anywhere.
if you call (defn add-pair [a b] (+ a b)) then it saves the function into the namespace and then the doc function is able to look it up later and print it's doc string.
A fn form evaluates to a function object.
You can apply the function object immediately:
((fn [a b] (+ a b)) 1 1) ;=> 2
If you want to refer to the function object locally, use a let
binding:
(let [add-pair (fn [a b] (+ a b))] (add-pair 1 1)) ;=> 2
A function object is as much a value as 1
or [3 :a]:
(let [double (fn [n] (* 2 n))]
(({double (comp double double)} double) 3)
;=> 12
The let binding does not exist within the fn form - you need a
name parameter for that:
((fn fact [n] (case n, 0 1, (* n (fact (dec n))))) 5) ;=> 120
letfn does both:
(letfn [(fact [n] (case n, 0 1, (* n (fact (dec n)))))] (fact 5)) ;=> 120
If you want the function to be accessible globally, bind it to a
var using def:
(def fact (fn fact [n] (case n, 0 1, (* n (fact (dec n))))))
(fact 5) ;=> 120
The defn macro does the same more succinctly:
(defn fact [n] (case n, 0 1, (* n (fact (dec n)))))
(fact 5) ;=> 120

Clojure idioms: sanely pass function-value pairs

Sometimes I want to pass argument-value pairs to a higher-order function, where the value I should pass is determined by the argument I pass. I want to be able to pass the argument without explicitly specifying the accompanying value. In particular, I'm interested in the case where the argument is itself a function.
Generic Example:
Here's a very generic example, where my-foo and my-bar are functions that I'm passing to higher-foo:
(higher-foo my-foo :option4 args) ;good
(higher-foo my-bar :option13 args) ;good
(higher-foo my-foo :option13 args) ;how stupid are you?! my-foo requires :option4!
Question: Is there a "standard" method for making :option4 or :option13 to be inferable by higher-foo so that I can just write (higher-foo my-foo) and (higher-foo my-bar)?
More Specific Example:
Bear in mind that there are better alternatives to the following code, but I'm just trying to put forward a concrete example of what I'm talking about:
(defn seq-has? [f n someseq]
(every? (partial apply f)
(partition n 1 someseq)))
(defn monotonicity [a b]
(<= a b))
(defn generalized-fib [a b c]
(= c (+ a b)))
(seq-has? monotonicity 2 someseq) should return true if the sequence is monotonic, false otherwise. (seq-has? generalized-fib 3 someseq) should return true if the sequence follows the generalized Fibonacci form, false otherwise.
But the "2" and "3" bother me. I could have an arbitrary number of properties to test for, and I don't want to have to remember the appropriate "magic numbers" for such calls.
Note: I know of two ways to do this, and for my own personal use, I suppose they both work. But I'm interested in what is idiomatic or considered best practice in the community. I'll post my answers, but I'm hoping there are more solutions.
Just make the predicate function itself take variadic arguments, and have it do the partitioning / recurring. Your monotonic? for instance already exists in core, and is called <=
(<= 1 2 4 5)
=> true
(<= 1 2 1 5)
=> false
Here's the source for the 1, 2 and variadic arg versions:
(source <=)
(defn <=
"Returns non-nil if nums are in monotonically non-decreasing order,
otherwise false."
{:inline (fn [x y] `(. clojure.lang.Numbers (lte ~x ~y)))
:inline-arities #{2}
:added "1.0"}
([x] true)
([x y] (. clojure.lang.Numbers (lte x y)))
([x y & more]
(if (<= x y)
(if (next more)
(recur y (first more) (next more))
(<= y (first more)))
false)))
You can make a fib? work the same way, have it take variadic arguments and recur over triples:
(defn fib?
[a b & [c & r]]
(if (= c (+ a b))
(if r
(recur b c r)
true)
false))
(fib? 0 1 1)
=> true
(fib? 2 3 5 8 13)
=> true
Since you are asking for a standard way how a function determines a not passed argument from one argument:
(defn f
([arg0] (case a :foo (f a :bar)
:baz (f a :quux)))
([arg0 arg1] ...))
Depending on your use case a different dispatch construct than case may be a better fit.
For your generic example this implies that higher-foo should determine the correct :option in the desired overload like demonstrated above.
In your specific example, you can't determine the n from the passed function. You need a more specific datastructure:
(defn seq-has? [{:keys [f n]} s]
(every? (partial apply f)
(partition n 1 s)))
(def monotonicity
{:f <=
:n 2})
(def generalized-fib
{:f #(= (+ %1 %2) %3)
:n 3})
(seq-has? monotonicity [1 2 3])
;; => true
This solution seems like a hack to me. Is it considered common/idiomatic? Use meta-data on the functions that define the property you are looking for:
(defn higher-foo [foo & args]
(apply foo (:option (meta foo))
args))
(def my-foo
(with-meta
(fn [a b] (println "I'm doing something cool"))
{:option :option4}))
;using it:
user=> (higher-foo my-foo arg)

where is the bug in this Clojure code?

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.

Single predicate to test for "self-evaluating" atoms in Clojure

At the home site of Clojure, there is the following statement:
Strings, numbers, characters, true,
false, nil and keywords evaluate to
themselves.
Is there a single combined predicate that tests for any of these, combining string?, number?, char?, true?, false?, nil?, and keyword?. Should I just use (complement symbol?)?
Maybe I'm missing something, but you could use the following to test for any of those conditions and return true if one is true:
(defn self-eval?
[x]
(or (string? x)
(number? x)
(char? x)
(keyword? x)
(true? x)
(false? x)
(nil? x)))
It's easy enough to write a macro that asks "does the given expression evaluate to itself". In fact this is a good example of tasks that can only be done with a macro because they need to see the argument both evaluated and unevaluated.
(defmacro selfp [a] `(= ~a (quote ~a)))
#'user/selfp
user> (selfp 1)
true
user> (selfp +)
false
user> (selfp [1 2])
true
user> (selfp '(+ 1 2 3))
false
While strings, numbers, characters, keywords, and the booleans are all self-evaluating, other things such as [1 2] are as well,so this may not be a useful test in general.
Another option is to create a function that uses a map:
(defn myclassifier? [x]
(let [types-I-care-about #{java.lang.Sring ...}]
(if (types-I-care-about (type x))
true
false)))
Another option which may have better performance is to use java's dynamism:
(extend-type Object
IMyClassifier
(myclassifier? [x]
(let [c (.getClass x)]
(if (types-I-care-about (type c))
(do
(extend-type (.getClass x)
IMyClassifier
(myclassifier? [x] true))
true)
false))))
where types-I-care-about is a set of types you care about.

Is there a function similar to "andmap" in clojure?

I want to apply a series of tests on my list and make sure that all the tests are passed.
Is there a function similar to "andmap" in Clojure?
You could use every?:
user=> (every? string? '("hi" 1))
false
Here's the documentation on every?.
Clojure 1.3 will add every-pred (and the related some-fn for the "or" version).
clojure.core/every-pred
([p] [p1 p2] [p1 p2 p3] [p1 p2 p3 & ps])
Takes a set of predicates and returns a function f that returns true if all of its
composing predicates return a logical true value against all of its arguments, else it returns
false. Note that f is short-circuiting in that it will stop execution on the first
argument that triggers a logical false result against the original predicates.
A naive implementation might be:
(defn every-pred [& preds] (fn [& args] (every? #(every? % args) preds)))
but the actual implementation will have better performance.
I wrote andmap as a macro which takes predicates as its arguments and builds a function that "wraps an and around the predicates", i.e.,
(andmap integer? odd?)
==>
(fn [x] (and (integer? x)
(odd? x)))
(it doesn't expand to exactly this, but it expands to something equivalent to this)
This has the advantage that it shortcuircuts on the predicates so you can write
(every? (andmap integer? odd?) [1 3 "a string"])
without getting a runtime exception as you would get with Arthurs answer.
Here is the definition of andmap:
(defmacro andmap
([] `(fn [& x#] true))
([p & ps] `(fn [& x#] (and (apply ~p x#)
(apply (andmap ~#ps) x#)))))
It is also possible to define andmap as an function which also short-circuits on it's predicates due to lazyness:
(defn andmap [& ps]
(fn [& x]
(every? true? (map (fn [p] (apply p x)) ps))))
The predicates to andmap can take an arbitrary number of arguments, so it is possible to write
(map (andmap #(and (integer? %1)
(integer? %2))
#(and (odd? %1)
(even? %2))
<)
[1 3 9]
[2 6 "string"])
which evaluates to (true true false).
every? will ask "Does this one function return true for each member of the seq", which is close to what I think you are asking for. An improvement on every? would take a list of functions and ask "Are all these predicates true for every member of this seq".
Here is a first attempt:
(defn andmap? [data tests]
(every? true? (for [d data, f tests]
(f d))))
user> (andmap? '(2 4 8) [even? pos?])
true
user> (andmap? '(2 4 8) [even? odd?])
false