How do I modify the :arglist attribute for a clojure fn or macro?
(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"}
Ok, no luck there, so I tried doing the following.
(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"}
Hmm, so now the :arglists key is gone? Well, I give up, how do I do this? I would simply like to modify the value of :arglists. The examples above use defn, but I would also like to know how to set the :arglists using a macro (defmacro).
You don't need to do anything as ugly as the suggestions so far. If you take a look at defn
's own 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?])
You're looking for attr-map
. Here's an example.
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
(In that case, arglists is a total lie. Don't do that!)
alter-meta! changes the metadata on a var. The metadata on the function is not relevant, only the var.
(alter-meta! #'tripler assoc :arglists '([b]))
defn does not leave room to mangle the metadata which is OK because it's just a macro that wraps def
. You can use def directly instead of 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"}
or you define the var tripler with defn:
core> (defn tripler [a] (* 3 a))
#'autotestbed.core/tripler
then redefine the var with the same contents and different metadata:
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"}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With