如何将:arglists修改为Clojure fn或宏?

Ste*_*gle 4 macros arguments clojure defn

如何修改Clojure FN或宏的:arglist属性?

(defn tripler ^{:arglists ([b])} [a] (* 3 a))

(defn ^{:arglists ([b])} quadrupler [a] (* 4 a))

% (meta #'tripler) => 
  {:arglists ([a]), :ns #<Namespace silly.testing>, :name tripler, :line 1, :file "NO_SOURCE_PATH"}

% (meta #'quadrupler) => 
  {:arglists ([a]), :ns #<Namespace silly.testing>, :name quadrupler, :line 1, :file "NO_SOURCE_PATH"}
Run Code Online (Sandbox Code Playgroud)

好的,那里没有运气,所以我尝试执行以下操作。

(def tripler
  (with-meta trippler
    (assoc (meta #'tripler) :arglists '([c]))))

% (with-meta #'tripler) => 
  {:ns #<Namespace silly.testing>, :name tripler, :line 1, :file "NO_SOURCE_PATH"}
Run Code Online (Sandbox Code Playgroud)

嗯,现在:arglists键不见了?好吧,我放弃了,我该怎么做?我只想修改:arglists的值。上面的示例使用defn,但我也想知道如何使用宏(defmacro)设置:arglists。

ama*_*loy 5

改变元!更改变量上的元数据。函数上的元数据无关,只有var。

(alter-meta! #'tripler assoc :arglists '([b]))
Run Code Online (Sandbox Code Playgroud)


due*_*ers 5

到目前为止,您不需要做任何像建议那样丑陋的事情。如果您查看 defn 自己的 arglists*...

user=> (:arglists (meta #'clojure.core/defn))
([name doc-string? attr-map? [params*] prepost-map? body]
 [name doc-string? attr-map? ([params*] prepost-map? body) + attr-map?])
Run Code Online (Sandbox Code Playgroud)

您正在寻找attr-map. 这是一个例子。

user=> (defn foo
         "does many great things"
         {:arglists '([a b c] [d e f g])}
         [arg] arg)
#'user/foo
user=> (doc foo)
-------------------------
user/foo
([a b c] [d e f g])
  does many great things
nil
Run Code Online (Sandbox Code Playgroud)

在这种情况下, arglists 完全是谎言。不要那样做!

*请注意,我使用的clojure.core/defn不仅仅是defn. 这有区别,我不知道为什么。同样与doc.