• (with-handler & forms)
This is error-kit's dynamic scope form. The body will be executed
in a dynamic context that includes all of the following 'handle' and
'bind-continue' forms.

0 Examples top

Log in to add / edit an example.

See Also top

Log in to add a see also.

Plus_12x12 Minus_12x12 Source clojure/contrib/error_kit.clj:163 top

(defmacro with-handler
  "This is error-kit's dynamic scope form.  The body will be executed
  in a dynamic context that includes all of the following 'handle' and
  'bind-continue' forms."
  [& forms]
  (let [[body special-forms] (split-with (complement special-form) forms)]
    (assert (every? special-form special-forms))
    (let [blockid (gensym)
          handlers (for [[type & more] special-forms
                         :when (= (resolve type) #'handle)]
                     (let [[htag args & hbody] (if (symbol? (first more))
                                                 more
                                                 (cons nil more))
                           argmap (if (vector? args) `{:keys ~args} args)]
                       `{:blockid '~blockid
                         :htag ~(when htag (list `quote (qualify-sym htag)))
                         :hfunc (fn [~argmap] ~@hbody)
                         :rfunc identity}))
          continues (into {}
                          (for [[type & more] special-forms
                                :when (= (resolve type) #'bind-continue)]
                            [(list `quote (first more))
                             `{:blockid '~blockid
                               :rfunc (fn ~@(next more))}]))]
      `(try
         (binding [*handler-stack* (list* ~@handlers @#'*handler-stack*)
                   *continues* (merge @#'*continues* ~@continues)]
           ~@body)
         (catch Throwable e#
           (let [root-cause# (root-cause e#)]
             (if-not (instance? @#'ctrl-exception-class root-cause#)
               (throw e#)
               (let [data# @root-cause#]
                 (if (= '~blockid (:blockid data#))
                   (apply (:rfunc data#) (:args data#))
                   (throw e#))))))))))
Vars in clojure.contrib.error-kit/with-handler: assert defmacro every? let = apply binding concat deref if-not instance? list list* merge seq vector
Used in 0 other vars

Comments top

No comments for with-handler. Log in to add a comment.