Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure function to get docstrings from functions in a namespace

Tags:

clojure

I want to write a function that returns the names and docstrings of the public functions in my namespace, like so:

(ns familiar.core
  (:require [clojure.repl :refer [doc]]
            ...))

;; various functions with docstrings here

(defn help 
  "Halp!"
  []
  (let [fns (keys (ns-publics 'familiar.core))]
    (for [f fns]
      [f (with-out-str (doc f))])))

When I call (help) in the REPL, the docstrings don't come with the functions:

familiar.core=> (help)
([save-experiment ""] [load-experiment ""] [add-data ""] [help ""] ... )

But calling (with-out-str (doc add-data)) in the REPL works as I'd expect:

familiar.core=> (with-out-str (doc add-data))
"-------------------------\nfamiliar.core/add-data\n([& coll])\n
Adds instances of variables with values at active date.\n  Examp
le:\n (add-data \"mice\" 6 \"cats\" 2 \"dogs\" 0)\n"

What's going on here?

like image 612
James Avatar asked Jun 14 '13 17:06

James


People also ask

What is FN in Clojure?

Most Clojure code consists primarily of pure functions (no side effects), so invoking with the same inputs yields the same output. defn defines a named function: ;; name params body ;; ----- ------ ------------------- (defn greet [name] (str "Hello, " name) )

What is REPL Clojure?

What is a REPL? A Clojure REPL (standing for Read-Eval-Print Loop) is a programming environment which enables the programmer to interact with a running Clojure program and modify it, by evaluating one code expression at a time.

What is Clojure namespace?

A namespace is both a name context and a container for vars. Namespace names are symbols where periods are used to separate namespace parts, such as clojure. string . By convention, namespace names are typically lower-case and use - to separate words, although this is not required.

What is NS Clojure?

Namespaces are mappings from simple (unqualified) symbols to Vars and/or Classes. Vars can be interned in a namespace, using def or any of its variants, in which case they have a simple symbol for a name and a reference to their containing namespace, and the namespace maps that symbol to the same var.


1 Answers

doc is a macro, so it cannot evaluate the local f in the calling context. Instead, you are simply calling (doc f) ovr and over.

The easiest approach to solve this is to go around the doc macro, and look directly at the data that it uses to produce documentation: metadata on vars.

(defn help 
  "Halp!"
  [x]
  (for [[name var] (ns-publics 'familiar.core)]
    [name (:doc (meta var))]))
like image 94
amalloy Avatar answered Nov 15 '22 07:11

amalloy