3

I have the following macro:

(defmacro ss [x]

`(clojureql.core/select 
      (clojureql.core/table db "users_table")
      (clojureql.core/where  ~x)
  )
)

(macroexpand '(ss '(= :type "special")))

: but it produces :

(clojureql.core/select (clojureql.core/table oe.db.dbcore/db "users_table") (clojureql.core/where '(= :type "special"))) 

: instead of :

(clojureql.core/select (clojureql.core/table oe.db.dbcore/db "users_table") (clojureql.core/where (= :type "special"))) 

: I realise that the problem is I am passing in a list '(= :type "special"), but how can I get this to unquote in the macro?

Update:

I finally got this working thanks to Mikera's answer by doing this:

(defn ss [x]

  (clojureql.core/select 
      (clojureql.core/table db "users_table")
      x
  )


)

(macroexpand '(ss (eval `(clojureql.core/where ~'(= :type "special")))))

: although the output is slightly different it works as expected:

(ss (eval (clojure.core/seq (clojure.core/concat (clojure.core/list 'clojureql.core/where) (clojure.core/list '(= :type "special")))))) 
3
  • I've used eval in such case. Just change ~x to ~(eval x). But I don't know, maybe there is another solution or you just misspelled with (= :type "special"). Commented Jul 7, 2011 at 19:43
  • When I use eval I get: (clojureql.core/select (clojureql.core/table oe.db.dbcore/db "users_table") (clojureql.core/where (clojure.core/eval quote (= :type "special")))) Commented Jul 7, 2011 at 19:57
  • 1
    It's really strange, for me eval is working (I tried (defmacro ss [x] `(* 3 ~(eval x))) (macroexpand '(ss '(+ 1 2)))). But if the code is expanded to (quote (= :type "special")) then I come to only one solution: to use ~(second x). But don't know why I don't like it. :) Commented Jul 7, 2011 at 20:26

2 Answers 2

3

Looks to me like you're passing the wrong thing to macroexpand: you should probably use:

(macroexpand '(ss (= :type "special")))

i.e. you ony need one quote at the beginning to quote the entire expression.

Sign up to request clarification or add additional context in comments.

6 Comments

I am using '(= :type "special") as it is passed around as a parameter in my program, as I cannot pass around (= :type "special") in Clojure without the '
Hmmm not quite sure what you mean... are you trying to expand the macro at runtime using eval? if so you can run the command with (eval `(ss ~parameter))
Zubair: quote quotes its entire argument. Have you tried mikera's suggestion?
Yes, that worked, thanks Mikera! I have updated the question to show what finally worked.
Why using eval, if (cadr xx) is sufficient (as long as the argument is always quoted)?
|
2

You cannot pass runtime arguments to macros since the former are only known at - well - runtime, while the latter are already expanded and compiled at - well - compile time.

You must use a function.

(defn get-users-by-type
  [t]
  (cql/select
    (cql/table db "users_table")
    (cql/where (= :type t))))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.