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.
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
In my app I'm providing some interface to users that they can provide code and app evaluates that code within sandbox(so eval fn not allowed).The thing is I need to catch if user overrides some built-in function such as =
Any ideas how to catch and prevent that thing?(The idea is they should not be able to do that)
Code:
(defn =
[]
//some code)
WARNING: = already refers to: #'clojure.core/= in namespace: user, being replaced by: #'user/=
One solution might be:
I was trying to get the warning message as String but with-out-str function did not work.
(with-out-str
(defn = []))
;=> ""
Also wrote that with-err-str(changed with-out-str little bit) did not work as well.
(defmacro with-err-str
[& body]
`(let [s# (new java.io.StringWriter)]
(binding [*err* s#]
~#body
(str s#))))
(with-err-str
(defn = []))
;=> ""
Need: "WARNING: = already refers to: #'clojure.core/= in namespace: user, being replaced by: #'user/="
It does work when you use eval:
user=> (with-err-str (eval '(defn - [] 11)))
"WARNING: - already refers to: #'clojure.core/- in namespace: user, being replaced by: #'user/-\n"
user=> (re-seq #"WARNING" (with-err-str (eval '(defn / [] 11))))
("WARNING")
Or you could redefine the defn macro in user's code, but nothing prevents them to use other clojure tools to redefine a var:
user=> (defmacro defn-safe
#_=> [nam & decls]
#_=> (if (resolve (symbol "clojure.core" (name nam)))
#_=> (print "Whoops")
#_=> (list* `defn (with-meta nam (assoc (meta nam) :private true)) decls)))
#'user/defn-safe
user=> (defn-safe foo [x] (+ x 2))
#'user/foo
user=> (foo 22)
24
user=> (defn-safe = [a b] (- a b))
Whoopsnil
user=>
Another option, and probably your best bet is using
https://github.com/clojure/tools.analyzer
clojail handles this (and many other things as well). If you're looking to sandbox Clojure, I'd recommend taking a look.
One solution might be like this:
(def before (set (vals (ns-map *ns*))))
(defn = [])
(def after (set (vals (ns-map *ns*))))
(clojure.set/difference before after)
;=> #{#'clojure.core/=}
While toying with Clojure I wrote a function, which relied on someSymbol being undefined at first run as (resolve someSymbol) would return nil. Turns out, that by defn-ing funcion with def somewhere in it causes the symbol to be defined:
(resolve 'someSymbol)
(defn resolvePokus []
(prn "I was evaluated")
(def someSymbol 1)
)
(resolve 'someSymbol)
in REPL yields:
nil
#'user/resolvePokus
#'user/someSymbol
Does that mean, that some special expressions are evaluated on running defn? Which ones?
Brief look into defn's source didn't reveal anything to me, except for there is one TODO comment in this core function :)
I assume you are running in the repl. I do not see the behavior you describe:
clj.core=> (resolve 'someSymbol)
nil
clj.core=> (defn resolvePokus []
#_=> (prn "I was evaluated")
#_=> (def someSymbol 1)
#_=> )
#'clj.core/resolvePokus
clj.core=> (resolve 'someSymbol)
#'clj.core/someSymbol
; try to use it -> error "Unbound..."
clj.core=> someSymbol
#object[clojure.lang.Var$Unbound 0x542f6481 "Unbound: #'clj.core/someSymbol"]
clj.core=> (resolvePokus) ; run the function
"I was evaluated"
#'clj.core/someSymbol
clj.core=> (resolve 'someSymbol) ; still can resolve
#'clj.core/someSymbol
clj.core=> someSymbol ; now we can use it
1
clj.core=> (declare xyz) ; creates a var, but unbound
#'clj.core/xyz
clj.core=> (resolve 'xyz) ; we can see resolve it
#'clj.core/xyz
clj.core=> xyz ; try to use it -> error "Unbound"
#object[clojure.lang.Var$Unbound 0x2d1d436f "Unbound: #'clj.core/xyz"]
clj.core=> (def xyz 5) ; define it
#'clj.core/xyz
clj.core=> (resolve 'xyz) ; still can resolve
#'clj.core/xyz
clj.core=> xyz ; now we can use it
5
So when I define the function, after typing the final parentheses the repl prints that #'clj.core/resolvePokus is defined but not someSymbol. The final resolve call still returns nil.
However, if you read further it seems that Clojure does the equivalent of a (declare someSymbol) when it first sees the (def someSymbol 1). You can see the same behavior when I manually (declare xyz) and later give it a value via (def xyz 5)
You may wish to look at this answer. The details involve the "hidden" var and how it is the anonymous intermediary between the symbol xyz and the value 5.
P.S. The above example was run on Ubuntu 16.04, Clojure 1.8, Java 1.8
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))
Is there a way in clojure to get a function's code after the function has been loaded?
Ie. without doing something like [untested]
(defmacro blat [x] `(do (def code ~(quote (mexpand-all x)))
~x)))
(blat (defn func [abc] (...)))
You can get the source of a symbol using the clojure.repl/source function. However, this only works if the var for which the symbol resolves to is in a .clj file on the classpath. You can't, for example, do this:
user=> (defn foo [x] x)
#'user/foo
user=> (require 'clojure.repl)
nil
user=> (clojure.repl/source foo)
Source not found
nil