Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><strong>Explanation</strong></p> <p>The problem here is that <code>doc</code> is a macro, not a function. You can verify this with the <a href="http://clojuredocs.org/clojure_core/clojure.repl/source" rel="nofollow"><code>source</code></a> macro in the repl.</p> <pre><code>(source doc) ; (defmacro doc ; "Prints documentation for a var or special form given its name" ; {:added "1.0"} ; [name] ; (if-let [special-name ('{&amp; fn catch try finally try} name)] ; (#'print-doc (#'special-doc special-name)) ; (cond ; (special-doc-map name) `(#'print-doc (#'special-doc '~name)) ; (resolve name) `(#'print-doc (meta (var ~name))) ; (find-ns name) `(#'print-doc (namespace-doc (find-ns '~name)))))) </code></pre> <p>If you're new to Clojure (and lisps), you might not have encountered macros yet. As a devastatingly brief explanation, where functions operate on <em>evaluated</em> code, macros operate on <em>unevaluated</em> code - that is, source code itself.</p> <p>This means that when you type</p> <pre><code>(doc (rand-nth (keys (ns-publics 'clojure.core)))) </code></pre> <p><code>doc</code> attempts to operate on the actual line of code - <code>(rand-nth (keys (ns-publics 'clojure.core)))</code> - rather than the evaluated result (the symbol this returns). Code being nothing more than a list in Clojure, this is why the error is telling you that a list can't be cast to a symbol.</p> <p><strong>Solution</strong></p> <p>So, what you really want to do is <em>evaluate</em> the code, then call <code>doc</code> on the result. We can do this by writing another macro which first evaluates the code you give it, then passes that to <code>doc</code>.</p> <pre><code>(defmacro eval-doc [form] (let [resulting-symbol (eval form)] `(doc ~resulting-symbol))) </code></pre> <p>You can pass <code>eval-doc</code> arbitrary forms and it will evaluate them before passing them to <code>doc</code>. Now we're good to go.</p> <pre><code>(eval-doc (rand-nth (keys (ns-publics 'clojure.core)))) </code></pre> <p><strong>Edit:</strong></p> <p>While the above works well enough in the repl, if you're using ahead ahead-of-time compilation, you'll find that it produces the same result every time. This is because the <code>resulting-symbol</code> in the <code>let</code> statement is produced during the compilation phase. Compiling once ahead of time means that this value is baked into the .jar. What we really want to do is push the evaluation of <code>doc</code> to runtime. So, let's rewrite <code>eval-doc</code> as a function.</p> <pre><code>(defn eval-doc [sym] (eval `(doc ~sym))) </code></pre> <p>Simple as that.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload