I'd like to add a :signature entry to the attr-map of defn, that
provides a haskell-style type signature to functions of the
single-arglist-body form.  I find the the normal way of providing
hints to a function:

(defn [ #^Class1 var1 #^Class2 var2 #^Class3 var3] ... )

is way too noisy, and the variables get lost between the types.  What
I'd like instead is to be able to specify the signature in the
function metadata:

(defn {:signature [ Class1 Class2 Class3 ReturnType ]}
  [ var1 var2 var3 ]
  ...)

I've written a little patch to defn that annotates the arguments
correctly (I think).  I'm not sure where the metadata for marking up a
function's return type goes (Is it on the (cons `fn fdecl) part?), but
it probably wouldn't be hard if I knew what I was doing :)

Anyhow, a revised defn (I've called it defn+ to avoid clashes) is as follows:

(defn zip [ a b ] (map vector a b))
(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))
                      (if (:signature m)
                        ; we'll apply the types in the signature vector as the
                        ; :tag metadata for each argument
                        (list
                          (cons
                            (apply vector
                              (for [[ tag var ]
                                    (zip (:signature m) (first fdecl))]
                                (with-meta var {:tag tag})))
                            (rest 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))

Is this something that people would think is worthwhile?  I really
prefer haskell's type signatures to clojure's inline hints, but maybe
it's just something that people get used to.  Anyhow, my first attempt
at macro hacking, so kind criticism would also be welcome w.r.t.
style, correctness, etc.

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to