Guest User

fn-reworked-pre

a guest
Jul 11th, 2011
164
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. (defn ^{:private true}
  2.   maybe-destructured
  3.   [params body]
  4.   (if (every? symbol? params)
  5.     (cons params body)
  6.     (loop [params params
  7.            new-params []
  8.            lets []]
  9.       (if params
  10.         (if (symbol? (first params))
  11.           (recur (next params) (conj new-params (first params)) lets)
  12.           (let [gparam (gensym "p__")]
  13.             (recur (next params) (conj new-params gparam)
  14.                    (-> lets (conj (first params)) (conj gparam)))))
  15.         `(~new-params
  16.           (let ~lets
  17.             ~@body))))))
  18.  
  19.  
  20. (defmacro fn
  21.   "params => positional-params* , or positional-params* & next-param
  22.  positional-param => binding-form
  23.  next-param => binding-form
  24.  name => symbol
  25.  
  26.  Defines a function"
  27.   {:added "1.0", :special-form true,
  28.    :forms '[(fn name? [params* ] exprs*) (fn name? ([params* ] exprs*)+)]}
  29.   [& sigs]
  30.     (let [name (if (symbol? (first sigs)) (first sigs) nil)
  31.           sigs (if name (next sigs) sigs)
  32.           sigs (if (vector? (first sigs)) (list sigs) sigs)
  33.           psig (fn* [sig]
  34.                  (let [[params & body] sig
  35.                        conds (when (and (next body) (map? (first body)))
  36.                                            (first body))
  37.                        body (if conds (next body) body)
  38.                        conds (or conds (meta params))
  39.                        pre (:pre conds)
  40.                        post (:post conds)                      
  41.                        body (if post
  42.                               `((let [~'% ~(if (< 1 (count body))
  43.                                             `(do ~@body)
  44.                                             (first body))]
  45.                                  ~@(map (fn* [c] `(assert ~c)) post)
  46.                                  ~'%))
  47.                               body)
  48.                        body (if pre
  49.                                 (concat (map  (fn* [c]
  50.                                               `(if (vector? ~c) (assert ~@c) (assert ~c)))
  51.                                             pre)
  52.                                       body)
  53.                               body)]
  54.                    (maybe-destructured params body)))
  55.           new-sigs (map psig sigs)]
  56.       (with-meta
  57.         (if name
  58.           (list* 'fn* name new-sigs)
  59.           (cons 'fn* new-sigs))
  60.         (meta &form))))
Advertisement
Add Comment
Please, Sign In to add comment