1

特定のシンボルのメタデータを調べて、キーワードではないエントリを削除するマクロを作成しています。つまり、キー名が「:」で始まっていません。

(meta (var X))  ;; Here's the metadata for testing...
=>
{:line 1,
 :column 1,
 :file "C:\\Users\\Joe User\\AppData\\Local\\Temp\\form-init11598934441516564808.clj",
 :name X,
 :ns #object[clojure.lang.Namespace 0x12ed80f6 "thic.core"],
 OneHundred 100,
 NinetyNine 99}

「OneHundred」と「NinetyNine」のエントリを削除し、残りのメタデータはそのままにしておきたいです。

だから私は動作するコードを少し持っています:

    (let [Hold# (meta (var X))]  ;;Make a copy of the metadata to search.
      (map (fn [[kee valu]]      ;;Loop through each metadata key/value.
        (if
          (not= \: (first (str kee)))  ;; If we find a non-keyword key,
          (reset-meta! (var X) (dissoc (meta (var X)) kee))  ;; remove it from X's metadata.
          )
        )
       Hold#  ;;map through this copy of the metadata.
      )
    )

できます。X のメタデータから「OneHundred」と「NinetyNine」のエントリが削除されました。

次に、それをマクロにコーディングします。神はREPLを祝福します。

(defmacro DelMeta! [S]  
  `(let [Hold# (meta (var ~S))] ;; Hold onto a copy of S's metadata.
     (map                       ;; Scan through the copy looking for keys that DON'T start with ":"
       (fn [[kee valu]]
         (if                    ;; If we find metadata whose keyname does not start with a ":"
           (not= \: (first (str kee)))
           (reset-meta! (var ~S) (dissoc (meta (var ~S)) kee))  ;; remove it from S's metadata.
           )
         )
       Hold#        ;; Loop through the copy of S's metadata so as to not confuse things.
       )
     )
  )

defmacro を使用してマクロを定義すると、エラーは発生しません。
マクロの macroexpand-1 、例えば

(macroexpand-1 '(DelMeta! X))

適切なコードに展開されます。ここ:

(macroexpand-1 '(DelMeta! X))
=>
(clojure.core/let
 [Hold__2135__auto__ (clojure.core/meta (var X))]
 (clojure.core/map
  (clojure.core/fn
   [[thic.core/kee thic.core/valu]]
   (if
    (clojure.core/not= \: (clojure.core/first (clojure.core/str thic.core/kee)))
    (clojure.core/reset-meta! (var X) (clojure.core/dissoc (clojure.core/meta (var X)) thic.core/kee))))
  Hold__2135__auto__))

しかし!!!

実際に REPL で実際のパラメーターを使用してマクロを呼び出すと、最も理解できないエラー メッセージが表示されます。

(DelMeta! X)  ;;Invoke DelMeta! macro with symbol X.

Syntax error macroexpanding clojure.core/fn at (C:\Users\Joe User\AppData\Local\Temp\form-init11598934441516564808.clj:1:1).
([thic.core/kee thic.core/valu]) - failed: Extra input at: [:fn-tail :arity-1 :params] spec: :clojure.core.specs.alpha/param-list
(thic.core/kee thic.core/valu) - failed: Extra input at: [:fn-tail :arity-n :params] spec: :clojure.core.specs.alpha/param-list

ああ、全能にして賢明なクロジュレゴッドよ、慈悲を乞う。私の罪はどこにありますか?

4

1 に答える 1