Как добавить мета / комментарий к последовательности, определенной через def в Clojure? - PullRequest
4 голосов
/ 11 декабря 2010

Мне пришлось закомментировать строку ниже (пример от http://en.wikibooks.org/wiki/Clojure_Programming/Examples/Lazy_Fibonacci)

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

Если бы я оставил это, я бы получил:

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

Однако я могу сделать это с defn. Пример (я знаю, я заново изобретаю колесо для even? уже определено):

(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=>

Ответы [ 3 ]

4 голосов
/ 11 декабря 2010

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

(:doc (meta (var fibs)))

; "Implements Fib. sequence lazily."


Достаточно просто написать макрос, чтобы вы могли написать (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)."


Также обратите внимание, что в вашем примере использования defn строка документации должна предшествовать аргументам, иначе она не будет связана с метаданными символа.


В качестве альтернативы можно использовать clojure.contrib.def / defvar .

4 голосов
/ 13 декабря 2010

Эта проблема «исправлена» уже в новых альфа-версиях Clojure 1.3, где def поддерживает необязательную строку документации.

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
0 голосов
/ 11 декабря 2010

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

(def символ init?) Создает и интернирует или находит глобальную переменную с именем символа и пространства имен значения текущего пространства имен.

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

(defn name doc-string? Attr-map? [params *] body) совпадает с (def name (fn [params *] exprs *)) с любой добавленной строкой документа или атрибутом к метаданным var.

Итак, когда вы пишете (def fib-seq «ваш комментарий» (...)), вы пытаетесь определить символ fib-seq со значением «ваш комментарий», и clojure жалуется, что аргументов слишком много.

...