I am trying to create a clojure macro that converts an entered symbol to a string. However, when I do this:
(defmacro convert-to-string [something]
`(call-converted "~something")
)
(macroexpand '(convert-to-string convert-this))
: I get :
(call-converted "~something")
: instead of :
(call-converted "~convert-this")
: does anyone show me how I could do this?
You might consider using keywords (or quoted symbols) and a function, rather than a macro:
(defn convert-to-string [x] (call-converted (name x)))
(convert-to-string :foo)
(convert-to-string 'foo)
If you really want a macro:
(defmacro convert-to-string [x] `(call-converted ~(name x)))
(macroexpand-1 '(convert-to-string foo))
=> (user/call-converted "foo")
I am in no way an expert on macros, but would this solve your problem:
(defmacro to-str [expr] (str expr))
Related
This returns false.
(defmacro scratch [pattern]
`(= 'b (first ~pattern)))
(scratch '(b))
However, the output of the following is b.
(defmacro scratch2 [pattern]
`(first ~pattern))
(scratch2 '(b))
How do I setup the first macro to return true?
that is happening, because the 'b that you introduce in macro is namespaced:
example:
user> (defmacro nsmac []
`(namespace 'b))
user> (nsmac)
;;=> "user"
while the value you pass isn't:
user> (namespace (first '(b)))
;;=> nil
so, you can pass the namespaced symbol to a macro, like this:
user> (scratch '(user/b))
;;=> true
or you can fix you macro to use unnamespaced symbol (known trick with qoute-unquote):
(defmacro scratch [pattern]
`(= '~'b (first ~pattern)))
user> (scratch '(b))
;;=> true
but what you really want, is to check this one in compile-time, because this macro you have is better as a plain function, since it doesn't employ any macro-related goodness.
It could look like this:
(defmacro scratch [pattern]
(= 'b (first pattern)))
(scratch (b))
;;=> true
something about namespacing can be found in this article
I have the following macro:
(defmacro my-macro [k]
`(do
(def pair
[
k
~(symbol (str "-" (name k)))]
)))
...which expands to:
(macroexpand-1 `(my-macro :n/k))
(do (def user/pair [user/k -k]))
...but instead I would like it to expand to
(do (def user/pair [:n/k -k]))
How can I make the macro keep the keyword and its namespace?
Thanks!
You need to escape k from the syntax quote using ~k:
(defmacro my-macro [k]
`(def ~'pair [~k ~(symbol (str "-" (name k)))]))
I've made a few other changes here as well:
Idiomatic formatting. Don't put ( or [ at the end of a line -- and put closing ) and ] on the same line as the expression they close.
do is entirely superfluous here.
If you want the macro to expand to (def pair ...), then you need to
escape out of the syntax quote (~)
quote the symbol pair (i.e., 'pair)
Putting this together, you have ~'pair. The reason you have to do this is because, in Clojure, `<symbol> is read as (quote <current-namespace>/foo>), where <current-namespace> stands for the current namespace. But def doesn't take names that are namespaced. Hence the ~' dance.
(But you probably want to parameterize on pair anyway ... otherwise, it's not very useful to use my-macro more than once per namespace.)
Overall, this seems like a very odd macro. I don't know what you're trying to accomplish, but I would probably take a different approach.
you can use the namespace and name function to extract the parts you want from the keyword passed in and combine them as required:
user> (defmacro my-macro [k]
`(do
(def pair
[~(keyword (str (namespace k) "/" (name k)))
~(symbol (str "-" (name k)))])))
#'user/my-macro
user> (macroexpand-1 `(my-macro :n/k))
(do (def user/pair [:n/k -k]))
Revised Answer
There are 2 things a bit confusing about your question & I misread it earlier.
You should use a regular single-quote ' with macroexpand-1, not the back-tic `. The back-tick is normally used only in a macro definition to delineate a piece of "template code".
I just noticed that the arg in the macro definition is k, and the keyword you use in the example is :n/k. These duplicate names will cause confusion.
Let's restate the problem:
(ns clj.demo)
(defmacro my-macro [arg]
`(do
(def pair
[
arg
~(symbol (str "-" (name arg)))]
)))
(println (macroexpand-1 `(my-macro :n/k)))
;=> (do (def clj.demo/pair [clj.demo/arg -k]))
So we are in the clj.demo namespace, which gets applied to the symbols pair and arg. We need to substitue the argument arg using ~:
(ns clj.demo)
(defmacro my-macro [arg]
`(do
(def pair
[
~arg
~(symbol (str "-" (name arg)))]
)))
(println (macroexpand-1 '(my-macro :n/k)))
;=> (do (def clj.demo/pair [:n/k -k]))
Which is what you want.
I have the following macro :
(defmacro add-children [this children]
(map (fn [child] (list '.addChild this child)) children))
and I would like to create the following macro :
(defmacro defgom [name & body]
(let [sym (gensym)]
`(let [~sym (Model.)]
(add-children sym body)))))
Considering that Model is a Java class with an addChild function. I would like to expand defgom to
(let [*gensym* (Model.)]
(.addChild *gensym* (first body))
(.addChild *gensym* (second body))
...
(.addChild *gensym* (last body)))
When evaluated, the add-children macro gives the correct result (the list of .addChild). But I can't evaluate it in the defgom macro. I get a "Don't know how to create ISeq from: clojure.lang.Symbol". I tried with ~ or ~# (given that add-children returns a list), but none worked.
How to properly expand the macro inside the macro?
PS: I know I can do it with a function rather than the add-children macro, but I want to know if it's possible to do it with a macro.
Just change the last line to:
(add-children ~sym ~#body)
I have a question regarding how to define functions/macros which call other macros or special forms but where one of the symbols passed in needs to be dynamic.
The simplest version of this question is described below:
We can define variables using def
(def x 0)
But what if we wanted the name x to be determined programmatically so that we could do the equivalent of?
(let [a 'b]
(our-def a 3)) => user/b
We could try to define a function
(defn defn2 [sym val]
(def sym val))
However it does not do what we want
(def2 'y 1) => #'user/sym
At first it seems like a macro works (even though it seems like it would be unnecessary)
(defmacro def3 [sym val]
`(def ~sym ~val))
(def3 z 2) => user/z
but it is just superficial, because we're really right back where we started with regular def.
(let [a 'b]
(def3 a 3)) => user/a
I can do it if I use eval, but it doesn't seem like eval should be necessary
(defn def4 [sym val]
(eval `(def ~sym ~val)))
(let [a 'b]
(def4 a 4)) => user/b
If there are other built-in commands that could achieve this particular example, they are not really what I am looking for since def is just to show a particular example. There are macros more complicated than def that I might want to call and not have to worry about how they were internally implemented.
First: The right way to do this is to use macro that starts with def... since this is the way people have been doing defs and is of little surprise to the user.
To answer you question: Use intern:
(def foo 'bar)
(intern *ns* foo :hi)
(pr bar) ;; => :hi
(intern *ns* foo :hi2)
(pr bar) ;; => :hi2
If you want to use macros do this:
(def z 'aa)
(defmacro def3 [sym val]
`(def ~(eval sym) ~val))
(def3 z 2)
(pr aa) ;; => 2
I have a clojure macro:
(defmacro show
[x] `(show-fn ~x)
)
: which given :
(show hello)
I want to resolve to :
(show-fn 'hello)
: How can I do this?
user=> (defmacro show [x] `(~'show-fn '~x))
#'user/show
user=> (macroexpand '(show hello))
(show-fn (quote hello))
This is called 'symbol capture'. It keeps the symbol from being resolved in the current namespace, as with your example.