Some questions about core.clj implementation

5 views
Skip to first unread message

Angel Java Lopez

unread,
Nov 15, 2009, 8:51:21 AM11/15/09
to clo...@googlegroups.com
Hi people!

I'm working on reimplement core.clj using my own C# interpreter for a clojure-like language. Browsing in the 1.0.0 source code of core.clj, I have some questions:

1: this is defn definition:

(def

 #^{:doc "Same as (def name (fn [params* ] exprs*)) or (def
    name (fn ([params* ] exprs*)+)) with any doc-string or attrs added
    to the var metadata"
    :arglists '([name doc-string? attr-map? [params*] body]
                [name doc-string? attr-map? ([params*] body)+ attr-map?])}
 defn (fn defn [name & fdecl]
        (let [m (if (string? (first fdecl))
                  {:doc (first fdecl)}
                  {})
              fdecl (if (string? (first fdecl))
                      (next fdecl)
                      fdecl)
              m (if (map? (first fdecl))
                  (conj m (first fdecl))
                  m)
              fdecl (if (map? (first fdecl))
                      (next fdecl)
                      fdecl)
              fdecl (if (vector? (first fdecl))
                      (list fdecl)
                      fdecl)
              m (if (map? (last fdecl))
                  (conj m (last fdecl))
                  m)
              fdecl (if (map? (last fdecl))
                      (butlast fdecl)
                      fdecl)
              m (conj {:arglists (list 'quote (sigs fdecl))} m)]
          (list 'def (with-meta name (conj (if (meta name) (meta name) {}) m))
                (cons `fn fdecl)))))

(. (var defn) (setMacro))

Why the "posponed" setMacro? Why not add the :macro true to inital metadata, directly?

2) The cond macro is defined:

(defmacro cond
  "Takes a set of test/expr pairs. It evaluates each test one at a
  time.  If a test returns logical true, cond evaluates and returns
  the value of the corresponding expr and doesn't evaluate any of the
  other tests or exprs. (cond) returns nil."
  [& clauses]
    (when clauses
      (list 'if (first clauses)
            (if (next clauses)
                (second clauses)
                (throw (IllegalArgumentException.
                         "cond requires an even number of forms")))
            (cons 'clojure.core/cond (next (next clauses))))))

Why the need of add the full namespace name in the last cons?

Ok, but the first use of it is in:

(defn spread
  {:private true}
  [arglist]
  (cond
   (nil? arglist) nil
   (nil? (next arglist)) (seq (first arglist))
   :else (cons (first arglist) (spread (next arglist)))))

Where is defined :else keyword behaviour? I can't find how :else is defined to be managed in cond/if code

TIA

Angel "Java" Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Michael Wood

unread,
Nov 15, 2009, 9:18:06 AM11/15/09
to clo...@googlegroups.com
2009/11/15 Angel Java Lopez <ajlop...@gmail.com>:
[...]
> (defn spread
>   {:private true}
>   [arglist]
>   (cond
>    (nil? arglist) nil
>    (nil? (next arglist)) (seq (first arglist))
>    :else (cons (first arglist) (spread (next arglist)))))
>
> Where is defined :else keyword behaviour? I can't find how :else is defined
> to be managed in cond/if code

I don't know about your other questions, but I believe :else could be
replace by anything that is logically true. It's just a convention to
use ":else".

user=> (cond (zero? 42) "42 is zero"
:else "42 is not zero")
"42 is not zero"
user=> (cond (zero? 42) "42 is zero"
true "42 is not zero")
"42 is not zero"
user=> (cond (zero? 42) "42 is zero"
:something-that-is-logically-true "42 is not zero")
"42 is not zero"
user=> (cond (zero? 42) "42 is zero"
"otherwise, if the above is not true, then" "42 is not zero")
"42 is not zero"

--
Michael Wood <esio...@gmail.com>

Meikel Brandmeyer

unread,
Nov 15, 2009, 12:25:07 PM11/15/09
to clo...@googlegroups.com
Hi,

Am 15.11.2009 um 14:51 schrieb Angel Java Lopez:

> 2) The cond macro is defined:
>
> (defmacro cond
> "Takes a set of test/expr pairs. It evaluates each test one at a
> time. If a test returns logical true, cond evaluates and returns
> the value of the corresponding expr and doesn't evaluate any of the
> other tests or exprs. (cond) returns nil."
> [& clauses]
> (when clauses
> (list 'if (first clauses)
> (if (next clauses)
> (second clauses)
> (throw (IllegalArgumentException.
> "cond requires an even number of forms")))
> (cons 'clojure.core/cond (next (next clauses))))))
>
> Why the need of add the full namespace name in the last cons?

If you don't qualify the recursive call, you'll get in trouble if a
user namespace defines its own cond. clojure.core/cond will then call
the original cond, but the expansion would call the user defined one.
And suddenly you are name capture hell. Fully qualifying the recursive
call is avoiding this issue.

Note, the syntax-quote is not yet available at that point of core.clj!

Sincerely
Meikel

Reply all
Reply to author
Forward
0 new messages