diff --git a/src/special/core.cljc b/src/special/core.cljc index 9c452eb..5a6a6e6 100644 --- a/src/special/core.cljc +++ b/src/special/core.cljc @@ -1,8 +1,9 @@ -(ns special.core) +(ns special.core + (:require [clojure.walk :as walk])) (defonce ^:dynamic *-special-condition-handlers-* {}) -(defn- manage-with-courage +(defn- manage-eager-conditions "Takes an eager function f and an \"inlined\" map of conditions to handlers. Returns a function in which these conditions are managed. @@ -24,17 +25,25 @@ (binding [*-special-condition-handlers-* (merge *-special-condition-handlers-* restarts)] (apply f args)))) +(defmulti eager (fn [type _] type)) +(defmethod eager ::postwalk [_ v] + (walk/postwalk (constantly nil) v) v) +(defmethod eager ::default [_ v] + (pr-str v) v) +(defmethod eager :default [_ v] + (eager ::default v)) + (defn- eagerize "Turns a lazy function into an eager function, at the run-time cost of using pr-str to fully realize the function result." - [f] + [eager-method f] (fn [& args] - (let [res (apply f args) - _ (pr-str res)] - res))) + (if (keyword? eager-method) + (eager eager-method (apply f args)) + (eager-method (apply f args)) ))) -(defn manage +(defn manage-as "Takes a function f and an \"inlined\" map of conditions and keywords. Returns a function in which these conditions are managed. @@ -43,9 +52,15 @@ f is allowed to be lazy, but the result must be finite, as it will always be fully realized. In other words: manage returns an eager function." + [type f & restarts] + (apply manage-eager-conditions (eagerize type f) restarts)) + +(defn manage-with + [eager-fn f & restarts] + (apply manage-eager-conditions (eagerize eager-fn f) restarts)) - [f & restarts] - (apply manage-with-courage (eagerize f) restarts)) +(def manage (partial manage-with #(do (pr-str %) %))) +;; or (def manage (partial manage-as ::default)) (defn condition "Raise a condition c with optional value v and optionally an \"inlined\" map of conditions to handlers.