3

シンボルを自動的に解決する方法があることを常に考えています。たとえば、「ユーザー」名前空間にいて、「clojure.string」名前空間でシンボルを「使用」していない場合、次の代わりに:

(clojure.string/split "a-b-c" #"-")

私はこのように書きたい:

(call split "a-b-c" #"-")

次のように「call」マクロを単純に実装しました。

(defmacro call [sym & args]
  `(let [fn# (first (distinct (remove nil? (map #(ns-resolve % '~sym) (all-ns)))))]
     (if-not ((meta fn#) :macro) 
       (fn# ~@args)
       (eval (list fn# ~@(map #(list 'quote %) args))))))

次のテストは常に問題ありません。

(call list 'a 'b)
(call apropos "list")
(call doc list)
(call doc clojure.string/split)

「doc」の引数としてマクロを渡すと、問題が発生します。

(call doc clojure.repl/doc)

次に、例外があります。

CompilerException java.lang.RuntimeException: マクロの値を取得できません: #'clojure.repl/doc、コンパイル中:(NO_SOURCE_PATH:112)

だから?ありがとう

4

1 に答える 1

2

次のように、マクロでコンパイル時にシンボルを解決できます。

(defmacro call [sym & args]
  (let [f (first (distinct (remove nil? (map #(ns-resolve % sym) (all-ns)))))]
      `(~f ~@args)))
于 2012-12-27T07:47:19.657 に答える