This library provides abstractions for dealing with errors and "exceptional" conditions with tools outside of Java exceptions.
The rp.condition
namespace provides a simple condition system for Clojure, inspired by Chris Houser's Condition Systems in an Exceptional Language. It's primary purpose is to provide a set of public, shared conditions to be used across libraries and applications within an organization. See rp.condition
for the public conditions provided. Unless otherwise rebound, conditions in this library will throw a clojure.lang.ExceptionInfo
exception.
The rp.condition.result
namespace provides a simple result type in the spirit of Rust's Result. The result
function builds a result, and the unwrap
and with-result
forms provide a means to handle the "ok" and "error" scenarios of a given result value.
It is not uncommon for timeouts to occur when communicating over a network. This library includes a rp.condition/*timeout*
condition that represents this "exceptional" condition.
If you use *timeout*
in isolation, it will throw an exception:
(require '[rp.condition :refer [*timeout*]])
(defn make-networked-call [args]
(let [fut (future (network-call args))
result (deref fut 1000 ::timeout)]
(if (= result ::timeout)
(*timeout* "Request to foo timed out." {:args args})
result)))
By using the dynamically-scoped nature of Clojure's dynamic var's, you can rebind *timeout*
at a higher level in your call stack to change what it returns when called. In this case, we return an empty result vector instead of throwing an exception, assumably because in this part of our code base, a failure to complete make-networked-call
is not a crucial operation:
;; Higher up the call stack:
(binding [*timeout* (constantly [])]
(make-networked-call [:a :b :c]))
;; Returns response from the network call if
;; it doesn't timeout, else []
An error condition is one that, when rebound, provides the ability of code higher in the call stack to inject default values into lower levels of the code. This can be a static default value, as shown in the timeout example above, or a value computed based on runtime values.
Restarts in a condition system support choosing one or more code branches to follow depending on the nature of the exceptional situation at runtime. This library does not currently include the machinery for restarts, but it can be added when the need arises.
Copyright © 2016 RentPath, LLC.
Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.