如何抓住已经提到:#和#x27;clojure.core/=在命名空间:user中,替换为:#';用户/=”;在Clojure?
在我的应用程序中,我为用户提供了一些界面,他们可以提供代码,并且应用程序在沙盒中评估代码(因此如何抓住已经提到:#和#x27;clojure.core/=在命名空间:user中,替换为:#';用户/=”;在Clojure?,clojure,Clojure,在我的应用程序中,我为用户提供了一些界面,他们可以提供代码,并且应用程序在沙盒中评估代码(因此evalfn是不允许的)。问题是,如果用户覆盖了一些内置函数,例如= 有没有办法抓住并阻止这件事 代码: (defn = [] //some code) WARNING: = already refers to: #'clojure.core/= in namespace: user, being replaced by: #'user/= 一种解决方案可能是: 我试图以String的形式获
eval
fn是不允许的)。问题是,如果用户覆盖了一些内置函数,例如=
有没有办法抓住并阻止这件事
代码:
(defn =
[]
//some code)
WARNING: = already refers to: #'clojure.core/= in namespace: user, being replaced by: #'user/=
一种解决方案可能是:
我试图以String
的形式获取警告消息,但with out str
函数不起作用
(with-out-str
(defn = []))
;=> ""
还写道,带有err str的(在没有str的情况下更改)也不起作用
(defmacro with-err-str
[& body]
`(let [s# (new java.io.StringWriter)]
(binding [*err* s#]
~@body
(str s#))))
(with-err-str
(defn = []))
;=> ""
需要:“警告:=已在命名空间:user中引用:#'clojure.core/=被替换为:#'user/=”
使用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")
或者您可以在用户代码中重新定义defn
宏,但没有任何东西阻止他们使用其他clojure工具重新定义变量:
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=>
另一个选择,也许你最好的选择是使用
处理这个(以及许多其他事情)。如果您正在寻找sandbox Clojure,我建议您看看。一个解决方案可能是这样的:
(def before (set (vals (ns-map *ns*))))
(defn = [])
(def after (set (vals (ns-map *ns*))))
(clojure.set/difference before after)
;=> #{#'clojure.core/=}
>他们可以提供代码,应用程序会评估这些代码,然后你们怎么做?(编辑问题plz)是的,你是对的,但有一些内部的事情我没有说,我想我需要说,因为它在沙箱中运行eval fn是不允许的:/但我真的很喜欢你的答案,我会尝试让它对我的用例起作用我已经在使用clojail了,是的,它也起作用了!(让[writer(java.io.StringWriter.)](sb)(println“blah”){#err writer}(str writer));返回“blah\n”