Reputation: 541
(defn fun
[& args]
(println args))
(fun (+ 1 1) (+ 1 1))
I want the output of fun
to be ((+ 1 1) (+ 1 1))
. I know quoting a form can make it unevaluated. But when I quote args
as below,
(defn fun
[& args]
(println 'args))
the output is args
, though. How can I do this?
Upvotes: 2
Views: 602
Reputation: 29984
One trick that is sometimes handy when there is more than one arg that needs quoting is to wrap everything in a vector, so as to avoid quoting each arg separately. Consider:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test) )
(defn foo
[args] ; not rest args. no `&` present!
(spyx args))
(dotest
(foo (quote [(+ 1 2) (+ 3 4)])) ; sometimes this is easier to read & manipulate
(foo '[(+ 1 2) (+ 3 4)]) ; this is a reader shortcut for the above
(let [x 4]
(foo `[(+ 1 2) (+ 3 ~x)]) ; backquote is handy, and always fully-qualifies Var names
))
with result
-------------------------------
Clojure 1.10.1 Java 14
-------------------------------
Testing tst.demo.core
args => [(+ 1 2) (+ 3 4)]
args => [(+ 1 2) (+ 3 4)]
args => [(clojure.core/+ 1 2) (clojure.core/+ 3 4)]
We see we only need to quote the wrapping vector, not each item inside it. This also shows that the single-quote is a reader shortcut for the (quote ...)
special form.
The last example shows that we may use the syntax-quote (i.e. backquote). It allows us to insert values into a template as with x
here. Since it is designed for macros, it adds the namespace to all Var references (i.e. the +
function here).
Upvotes: 1
Reputation: 51551
Clojure, like all non-lazy languages (which are almost all), evaluates arguments to a function call before calling the function. When you call:
(foo (+ 1 1) (+ 1 1))
first the arguments are evaluated
(foo 2 2)
then the function is called, so in your foo
, args
is (2 2)
. There is no connection to the forms that produced those values.
If you want to prevent evaluation, you need to quote before evaluation, i. e. in your calling form:
(defn foo [& args]
(println args))
(foo '(+ 1 1) '(+ 1 1))
Upvotes: 3