如何修改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"}
好的,那里没有运气,所以我尝试了以下几点。
(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"}
嗯,所以现在:arglists键消失了?好吧,我放弃了,我该怎么做?我只想修改:arglists的值。上面的例子使用defn,但我也想知道如何使用宏(defmacro)设置:arglists。
答案 0 :(得分:5)
alter-meta!更改var上的元数据。函数的元数据不相关,只有var。
(alter-meta! #'tripler assoc :arglists '([b]))
答案 1 :(得分:4)
到目前为止,你不需要做任何丑陋的事情。如果你看看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?])
您正在寻找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
在这种情况下,arglists是一个完全谎言。不要那样做!
*请注意,我使用的是clojure.core/defn
,而不仅仅是defn
。它有所作为,我不知道为什么。与doc
一样。
答案 2 :(得分:3)
defn不会留下空间来破坏元数据,因为它只是一个包裹def
的宏。您可以直接使用def而不是defn:
core> (def ^{:arglists '([b])} tripler (fn [a] (* 3 a)))
#'core/tripler
core> (meta #'tripler)
{:arglists ([b]), :ns #<Namespace autotestbed.core>, :name tripler, :line 1, :file "NO_SOURCE_FILE"}
或者用defn定义var tripler:
core> (defn tripler [a] (* 3 a))
#'autotestbed.core/tripler
然后使用相同的内容和不同的元数据重新定义var:
core> (def ^{:arglists '([b])} tripler tripler)
#'autotestbed.core/tripler
autotestbed.core> (meta #'tripler)
{:arglists ([b]), :ns #<Namespace autotestbed.core>, :name tripler, :line 1, :file "NO_SOURCE_FILE"}
答案 3 :(得分:1)
扩大合金的答案(请给予他信任):
user=> (defn foo "prints bar" [] (println "bar"))
#'user/foo
user=> (doc foo)
-------------------------
user/foo
([])
prints bar
nil
user=> (meta #'foo)
{:arglists ([]), :ns #<Namespace user>, :name foo, :doc "prints bar", :line 1, :file "NO_SOURCE_PATH"}
user=> (alter-meta! #'foo assoc :arglists '([blah]))
{:arglists ([blah]), :ns #<Namespace user>, :name foo, :doc "prints bar", :line 1, :file "NO_SOURCE_PATH"}
user=> (doc foo)
-------------------------
user/foo
([blah])
prints bar
nil
user=> (meta #'foo)
{:arglists ([blah]), :ns #<Namespace user>, :name foo, :doc "prints bar", :line 1, :file "NO_SOURCE_PATH"}
user=> (foo)
bar
nil
偷偷摸摸!