开发者

How to add a meta/comment to a sequence defined via def in Clojure?

开发者 https://www.devze.com 2023-01-29 21:15 出处:网络
I had to comment out the line below (example is from http://en.wikibooks.org/wiki/Clojure_Programming/Examples/Lazy_Fibonacci)

I had to comment out the line below (example is from http://en.wikibooks.org/wiki/Clojure_Programming/Examples/Lazy_Fibonacci)

(def fib-seq
开发者_C百科  ;"Implements Fibonacci sequence (starts with 0)."
  ((fn rfib [a b] 
     (lazy-seq (cons a (rfib b (+ a b)))))
   0 1))

If I left it in, I would get:

Clojure 1.2.0
java.lang.Exception: Too many arguments to def (Problem1.clj:1)
1:1 user=>

I can do this with defn, however. Example (I know, I am reinventing the wheel for even? is already defined):

(defn is-even? [n]
  "Returns true if the number is even, false otherwise."
  (== (mod n 2) 0))


Clojure 1.2.0
1:1 user=> (is-even? 3)
false
1:2 user=> (is-even? 4)
true
1:3 user=>


(def ^{:doc "Implements Fib. sequence lazily."} fibs ...)

(:doc (meta (var fibs)))

; "Implements Fib. sequence lazily."


It's simple enough to write a macro so you could write (def-with-docs foo "doc" 1).

(defmacro def-with-docs [name docstring value]
  `(def ~(with-meta name {:doc docstring}) ~value))

(def-with-docs fib-seq "Implements Fibbonaci sequence (starts with 0)."
  ((fn rfib [a b] (lazy-seq (cons a (rfib b (+ a b))))) 0 1))

(:doc (meta (var fib-seq)))

; "Implements Fibbonaci sequence (starts with 0)."


Also, note that with your example use of defn, the docstring should precede the arguments, else it won't be associated with the symbol's metadata.


Alternatively, one can use clojure.contrib.def/defvar.


This issue is "fixed" already in the new alpha releases for Clojure 1.3, where def supports an optional docstring.

user> (clojure-version)
"1.3.0-alpha3"

user> (def answer "the answer to the final question" 42)
#'user/answer

user> (doc answer)
-------------------------
user/answer
nil
  the answer to the final question
nil


From http://clojure.org/special_forms#def

(def symbol init?) creates and interns or locates a global var with the name of symbol and a namespace of the value of the current namespace.

From http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/defn

(defn name doc-string? attr-map? [params*] body) is the same as (def name (fn [params* ] exprs*)) with any doc-string or attrs added to the var metadata.

So, when you write (def fib-seq "your comment" (...)), you are trying to define a symbol fib-seq with value "your comment", and clojure complains there are too many arguments.

0

精彩评论

暂无评论...
验证码 换一张
取 消