Quick Search
Browse
Pages
Blog
Labels
Attachments
Mail
Advanced
What’s New
Space Directory
Feed Builder
Keyboard Shortcuts
Confluence Gadgets
Log In
Sign Up
Dashboard
Clojure Design
Copy Page
You are not logged in. Any changes you make will be marked as
anonymous
. You may want to
Log In
if you already have an account. You can also
Sign Up
for a new account.
This page is being edited by
.
Paragraph
Paragraph
Heading 1
Heading 2
Heading 3
Heading 4
Heading 5
Heading 6
Preformatted
Quote
Bold
Italic
Underline
Colour
More colours
Strikethrough
Subscript
Superscript
Monospace
Clear Formatting
Bullet list
Numbered list
Outdent
Indent
Align left
Align center
Align right
Link
Table
Insert
Insert Content
Image
Link
Attachment
Symbol
Emoticon
Wiki Markup
Horizontal rule
tinymce.confluence.insert_menu.macro_desc
Info
JIRA Issue
Status
Gallery
Tasklist
Table of Contents
Other Macros
Undo
Redo
Keyboard Shortcuts Help
<h3>Problems</h3> <ul> <li>platform uses types for dispatch <ul> <li>only error handling is platform error handling</li> </ul> </li> <li>want to carry data payloads <ul> <li>platform exceptions don't</li> </ul> </li> <li>need out-of-band communication <ul> <li>for both ordinary and exceptional things! <ul> <li>exceptional things are ordinary during development</li> </ul> </li> <li>and ways to discover the oob mechanisms</li> </ul> </li> <li>can't deal with exception at point it happens <ul> <li>can't resume</li> </ul> </li> <li>cannot manipulate exceptions as data</li> </ul> <h3>Symptoms</h3> <ul> <li>new application problems beget new types <ul> <li>types are heavy</li> <li>why don’t people use an existing type? <ul> <li>want to branch on it (flow control)</li> <li>habit</li> <li>carry data</li> </ul> </li> </ul> </li> <li>new exception types lead to <ul> <li>gen-class (+ precompilation)</li> <li>Java classes in Clojure projects</li> </ul> </li> <li>use big things to solve small problems <ul> <li>condition library (e.g. <a href="https://github.com/clojure/clojure-contrib/blob/master/modules/condition/src/examples/clojure/examples/condition.clj">Contrib Condition</a>) when all you want is data</li> <li>exceptions when all you want is control flow <ul> <li>idiomatic on many JVM languages</li> <li>don't have composite returns or dynamic binding</li> </ul> </li> </ul> </li> <li>can't troubleshoot problems <ul> <li>info is gone when call stack unwinds</li> </ul> </li> </ul> <h3>Example Use Cases</h3> <ul> <li>communicate ordinary things <ul> <li>recover from I/O failure</li> <li>convey detailed information for reporting in test framework</li> </ul> </li> <li>communicate exceptional things <ul> <li>program bugs</li> <li>platform and hardware failures</li> </ul> </li> <li>jump to debugger based on situation</li> <li>add information to an exception <ul> <li>e.g. Alan's adorning macro arity example</li> </ul> </li> <li>troubleshoot build failure that is only on Hudson</li> </ul> <h3>Constraints</h3> <ul> <li>dispatch should be fast <ul> <li>where exceptions are used for exceptional things, performance is not an issue</li> </ul> </li> <li>error handling should unify at bottom with Java</li> <li>neither ordinary nor exceptional things should have to pollute API for fns that don't care or can't respond <ul> <li>pay for what you need</li> </ul> </li> </ul> <h3>An even-more modest proposal</h3> <p>I think we should implement</p> <ul> <li>education on dynamic bindings</li> <li>bindable <code>*assertion-handler*</code></li> <li>(maybe) clj-stacktrace-like data-ification fns for exceptions</li> <li>(maybe) data-carrying <code>*RuntimeException*</code> subclass</li> </ul> <p>All of these ideas, and several others not chosen, are documented below.</p> <h3>Some approaches</h3> <p>Table of some approaches and how they address the problems above. Approaches described in more detail below. Some of the approaches are deliberately crazy for contrast (wonder if we will agree on which ones).</p> <table class="confluenceTable"><tbody> <tr> <th class="confluenceTh"><p> Approach </p></th> <th class="confluenceTh"><p> Type Dispatch </p></th> <th class="confluenceTh"><p> Data Payloads </p></th> <th class="confluenceTh"><p> Out-of-band Communication </p></th> <th class="confluenceTh"><p> Action at Point of Exception </p></th> <th class="confluenceTh"><p> Exceptions as Data </p></th> <th class="confluenceTh"><p> Notes </p></th> </tr> <tr> <td class="confluenceTd"><p> education on dynamic binding </p></td> <td class="confluenceTd"><p> <span style="color: rgb(0,0,255);"><strong>solves</strong></span> </p></td> <td class="confluenceTd"><p> n/a </p></td> <td class="confluenceTd"><p> <span style="color: rgb(0,0,255);"><strong>solves</strong></span> </p></td> <td class="confluenceTd"><p> could solve </p></td> <td class="confluenceTd"><p> n/a </p></td> <td class="confluenceTd"><p> </p></td> </tr> <tr> <td class="confluenceTd"><p> clj-stacktrace </p></td> <td class="confluenceTd"><p> should unify with dataification of exceptions, if any </p></td> <td class="confluenceTd"><p> n/a </p></td> <td class="confluenceTd"><p> n/a </p></td> <td class="confluenceTd"><p> n/a </p></td> <td class="confluenceTd"><p> <span style="color: rgb(0,0,255);"><strong>partially solves for non-Clojure types</strong></span> </p></td> <td class="confluenceTd"><p> </p></td> </tr> <tr> <td class="confluenceTd"><p> ad hoc conditions </p></td> <td class="confluenceTd"><p> worsens </p></td> <td class="confluenceTd"><p> could solve </p></td> <td class="confluenceTd"><p> worsens </p></td> <td class="confluenceTd"><p> solves </p></td> <td class="confluenceTd"><p> orthogonal <br class="atl-forced-newline" /> </p></td> <td class="confluenceTd"><p> worsens = replaces general mechanism with more specialized one </p></td> </tr> <tr> <td class="confluenceTd"><p> pattern-matching conditions </p></td> <td class="confluenceTd"><p> ? </p></td> <td class="confluenceTd"><p> could solve </p></td> <td class="confluenceTd"><p> worsens </p></td> <td class="confluenceTd"><p> solves </p></td> <td class="confluenceTd"><p> orthogonal </p></td> <td class="confluenceTd"><p> worsens = replaces general mechanism with more specialized one </p></td> </tr> <tr> <td class="confluenceTd"><p> data-carrying exception </p></td> <td class="confluenceTd"><p> could support pattern matching </p></td> <td class="confluenceTd"><p> <span style="color: rgb(0,0,255);"><strong>solves</strong></span> </p></td> <td class="confluenceTd"><p> n/a </p></td> <td class="confluenceTd"><p> n/a </p></td> <td class="confluenceTd"><p> <span style="color: rgb(0,0,255);"><strong>solves for Clojure types</strong></span> </p></td> <td class="confluenceTd"><p> </p></td> </tr> <tr> <td class="confluenceTd"><p> enrich exceptions with local context </p></td> <td class="confluenceTd"><p> n/a </p></td> <td class="confluenceTd"><p> enhanced </p></td> <td class="confluenceTd"><p> for errors only </p></td> <td class="confluenceTd"><p> n/a </p></td> <td class="confluenceTd"><p> enhanced </p></td> <td class="confluenceTd"><p> yuck: makes everybody pay for debug time support </p></td> </tr> <tr> <td class="confluenceTd"><p> bindable test/assertion handler </p></td> <td class="confluenceTd"><p> orthogonal </p></td> <td class="confluenceTd"><p> orthogonal <br class="atl-forced-newline" /> </p></td> <td class="confluenceTd"><p> <span style="color: rgb(0,0,255);"><strong>for assertions</strong></span> </p></td> <td class="confluenceTd"><p> <span style="color: rgb(0,0,255);"><strong>for assertions</strong></span> </p></td> <td class="confluenceTd"><p> n/a </p></td> <td class="confluenceTd"><p> </p></td> </tr> <tr> <td class="confluenceTd"><p> bindable throw handler </p></td> <td class="confluenceTd"><p> orthogonal <br class="atl-forced-newline" /> </p></td> <td class="confluenceTd"><p> orthogonal <br class="atl-forced-newline" /> </p></td> <td class="confluenceTd"><p> <span style="color: rgb(0,0,255);"><strong>for Clojure exceptions</strong></span> </p></td> <td class="confluenceTd"><p> <span style="color: rgb(0,0,255);"><strong>for Clojure exceptions</strong></span> </p></td> <td class="confluenceTd"><p> n/a </p></td> <td class="confluenceTd"><p> </p></td> </tr> <tr> <td class="confluenceTd"><p> platform-based handler </p></td> <td class="confluenceTd"><p> orthogonal <br class="atl-forced-newline" /> </p></td> <td class="confluenceTd"><p> orthogonal <br class="atl-forced-newline" /> </p></td> <td class="confluenceTd"><p> solves </p></td> <td class="confluenceTd"><p> solves </p></td> <td class="confluenceTd"><p> n/a </p></td> <td class="confluenceTd"><p> does it exist? </p></td> </tr> <tr> <td class="confluenceTd"><p> bindable edge handler </p></td> <td class="confluenceTd"><p> orthogonal <br class="atl-forced-newline" /> </p></td> <td class="confluenceTd"><p> orthogonal <br class="atl-forced-newline" /> </p></td> <td class="confluenceTd"><p> tries and fails </p></td> <td class="confluenceTd"><p> tries and fails </p></td> <td class="confluenceTd"><p> could help </p></td> <td class="confluenceTd"><p> yuck: perf, asymmetry, doesn't accomplish desired goal </p></td> </tr> <tr> <td class="confluenceTd"><p> wrap java exceptions </p></td> <td class="confluenceTd"><p> orthogonal <br class="atl-forced-newline" /> </p></td> <td class="confluenceTd"><p> orthogonal <br class="atl-forced-newline" /> </p></td> <td class="confluenceTd"><p> at Clojure boundary </p></td> <td class="confluenceTd"><p> n/a </p></td> <td class="confluenceTd"><p> could support </p></td> <td class="confluenceTd"><p> yuck; terrible perf, terrible asymmetry, or both </p></td> </tr> <tr> <td class="confluenceTd"><p> "modest proposal" above </p></td> <td class="confluenceTd"><p> <span style="color: rgb(0,0,255);"><strong>solves</strong></span> <br class="atl-forced-newline" /> </p></td> <td class="confluenceTd"><p> <span style="color: rgb(0,0,255);"><strong>solves</strong></span> <br class="atl-forced-newline" /> </p></td> <td class="confluenceTd"><p> <span style="color: rgb(0,0,255);"><strong>solves, with extra goodness for debug</strong></span><br class="atl-forced-newline" /> </p></td> <td class="confluenceTd"><p> <span style="color: rgb(0,0,255);"><strong>solves, with extra goodness for debug</strong></span><br class="atl-forced-newline" /> </p></td> <td class="confluenceTd"><p> <span style="color: rgb(0,0,255);"><strong>solves</strong></span> </p></td> <td class="confluenceTd"><p> what's not to like? see bottom of this page... </p></td> </tr> </tbody></table> <h3>Education on Dynamic Binding</h3> <p>Document dynamic binding as the "Clojure Way" to do out-of-band-control flow that is often done via exceptions on other JVM languages.</p> <ul> <li>find likely place within Clojure or Contrib and implement examplar</li> <li>write docs and tutorial</li> <li>add "control flow" link from exception handling parts of Clojure docs</li> </ul> <h3><a href="https://github.com/mmcgrana/clj-stacktrace">clj-stacktrace</a></h3> <ul> <li>define a standard vocabulary for data-izing the information in a clojure exception</li> <li>package in fns <ul> <li>do not call these fns automatically</li> <li>maybe provide REPL helpers that do</li> </ul> </li> <li>other parts of clj-stactkrace (color printing etc.) should remain tool features</li> <li>open questions <ul> <li>what do the REPL fns look like?</li> <li>might start with the data and wait to see how they get used</li> </ul> </li> </ul> <h3>Ad hoc conditions</h3> <p>E.g. <a href="https://github.com/clojure/clojure-contrib/blob/master/modules/condition/src/examples/clojure/examples/condition.clj">Contrib Condition</a> or <a href="https://github.com/clojure/clojure-contrib/blob/master/modules/error-kit/src/main/clojure/clojure/contrib/error_kit.clj">Contrib Error-Kit</a>.</p> <ul> <li>could unify with Java exceptions, or not</li> <li>could include data-carrying exception, or not</li> </ul> <p>Not carrying this idea forward at this point.</p> <h3>Pattern Matching Conditions</h3> <p>Pattern matching (a la <a href="https://github.com/dcolthorp/matchure">Matchure</a>), plus exceptions as data, plus dynamic binding.</p> <p>Not carrying this idea forward at this point.</p> <h3>Data-carrying exception</h3> <p>Single exception type that can carry data, allowing clojure data tools to be used to process exceptions.</p> <ul> <li>subclass RuntimeException? <ul> <li>or one new type for each family (error, runtime, assertion?)</li> </ul> </li> <li>unify keys with clj-stackrace or equivalent if that is also done</li> <li>open questions <ul> <li>what are the programmatic (non-interactive) uses of this data?</li> </ul> </li> </ul> <h3>Enrich exceptions with local context</h3> <ul> <li>add locals, bindings, kitchen sink to exceptions</li> <li>could be debug-only</li> <li>could be tied to throw, or only to assertions</li> </ul> <h3>Bindable test/assertion handler</h3> <ul> <li>Create a bindable <code>*assertion-handler*</code> that can run with full context at the point an assertion fails <ul> <li>application of dynamic binding to the problem "Assertion fails where I can't get a debugger" (e.g. Hudson)</li> <li>default behavior is to raise the error</li> <li>facilitates use of assertion as the primary/only mechanism for tests, instead of separate fns like <code>is</code></li> </ul> </li> <li>implicitly debug-only through tie to assertions <ul> <li>once assertions are debug-only, anyway</li> </ul> </li> <li>maybe assertions should never have been exceptions in the first place <ul> <li>more of a use case for handlers than for exceptions</li> <li>unexpected errors are, ironically, <strong>expected</strong> errors during development</li> </ul> </li> <li>making assertions handler-based solves my "assertions are backwards" rant <ul> <li>handler can do anything it needs to with local context</li> </ul> </li> <li>also decouples the Java enablement issue <ul> <li>clojure binding controls initial reaction</li> <li>Java -ea flag controls fallback behavior (assert or do nothing)</li> </ul> </li> <li>open questions <ul> <li>encourage test frameworks to bottom out at assert, instead of their own ad-hoc things?</li> <li>what does the fn take? <ul> <li>source code forms of the assertion</li> <li>want access to locals</li> </ul> </li> </ul> </li> <li>very useful on CI <ul> <li>dump everything you know</li> </ul> </li> </ul> <h3>Bindable throw handler</h3> <ul> <li>like the assertion handler, but tied to all (Clojure) throws</li> <li><code>*throw-handler*</code> should be available (in effect?) only under debug mode <ul> <li>pay for what you need</li> </ul> </li> <li>open questions <ul> <li>what does the fn take? <ul> <li>source code forms</li> <li>access to locals</li> <li>args to exception</li> </ul> </li> </ul> </li> <li>very useful in CI <ul> <li>dump everything you know</li> </ul> </li> </ul> <h3>Platform-based handler</h3> <p>Is there JVM support for automating handlers like the assert handler or throw handler? If these exist, and are flexible and easy to deploy, could use them instead of extending Clojure.</p> <ul> <li>not aware of any</li> <li>Clojure versions would work on other platforms</li> </ul> <h3>Bindable edge handler</h3> <ul> <li>try to make <strong>all</strong> exceptions handle-able by wrapping clojure/java boundary everywhere</li> <li>when exception from Java land hits Clojure boundary, call the handler before propagating it</li> <li>attempt here is to respond closer to the problem <ul> <li>but halfway between the problem and the outer handler isn't much better than a full stack unwind</li> <li>nothing special about the Clojure/Java boundary</li> </ul> </li> <li>pervasive implementation and performance issues</li> <li>non-idiomatic wrapping</li> <li>ok, this is a crazy idea</li> </ul> <h3>Weaknesses of the modest proposal</h3> <ul> <li>still no automatic way to discover relevant bindings <ul> <li>documentation, of course</li> <li>but no programmatic way to discover relevant situation handlers</li> <li>checked exceptions got this half-right</li> </ul> </li> <li>Java/Clojure boundary visible on exceptions-as-data <ul> <li>Clojure exception can give you everything</li> <li>with Java exception you have to ask by calling a fn</li> </ul> </li> <li>Java/Clojure boundary visible on throw handler <ul> <li>no straigtforward way to sneak into Java</li> </ul> </li> <li>if there is any commonality in how to write a bindable handler, it isn't captured here</li> <li>nothing stops an exception from being unnecessarily data-ized multiple times</li> </ul>
Attachments
Labels
Location
< Edit
Preview >
Loading…
Save
Cancel
Next hint
search
attachments
weblink
advanced