代码之家  ›  专栏  ›  技术社区  ›  Ertuğrul Çetin

如何捕捉“=已在命名空间:user中引用:#'clojure.core/=,被clojure中的:#'user/=”替换?

  •  3
  • Ertuğrul Çetin  · 技术社区  · 7 年前

    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 = [])) 
    ;=> ""
    

    还写道 with-err-str 不带str 一点点)也不起作用。

    (defmacro with-err-str
      [& body]
      `(let [s# (new java.io.StringWriter)]
         (binding [*err* s#]
           ~@body
           (str s#))))
    
    (with-err-str
     (defn = [])) 
    ;=> ""
    

    "WARNING: = already refers to: #'clojure.core/= in namespace: user, being replaced by: #'user/="

    3 回复  |  直到 7 年前
        1
  •  2
  •   skrat    7 年前

    当你使用 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=> 
    

    https://github.com/clojure/tools.analyzer

        2
  •  2
  •   Alex Miller    7 年前

    clojail 处理这个(以及许多其他事情)。如果你正在寻找沙盒Clojure,我建议你看看。

        3
  •  2
  •   Ertuğrul Çetin    7 年前

    (def before (set (vals (ns-map *ns*))))
    
    (defn = [])
    
    (def after (set (vals (ns-map *ns*))))
    
    (clojure.set/difference before after)
    
    ;=> #{#'clojure.core/=}