<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div>Would something like this work for what you want?</div><div><br></div><div><div><font face="Courier New">(define (boiler-plate/thunk thunk)</font></div><div><font face="Courier New"> (define err-msg #f)</font></div><div><font face="Courier New"> (let/ec fail-network</font></div><div><font face="Courier New"> (with-handlers ([exn:fail:network?</font></div><div><font face="Courier New"> (lambda (e)</font></div><div><font face="Courier New"> (set! err-msg "database connection error")</font></div><div><font face="Courier New"> (fail-network err-msg))])</font></div><div><font face="Courier New"> (let ([db (connect-database)])</font></div><div><font face="Courier New"> (let/ec fail-sql</font></div><div><font face="Courier New"> (with-handlers ([exn:fail:sql?</font></div><div><font face="Courier New"> (lambda (e)</font></div><div><font face="Courier New"> (let ([info (exn:fail:sql-info e)])</font></div><div><font face="Courier New"> (set! err-msg (cdr (assoc 'message info)))</font></div><div><font face="Courier New"> (fail-sql err-msg)))])</font></div><div><font face="Courier New"> (call-with-transaction db thunk #:isolation 'repeatable-read))</font></div><div><font face="Courier New"> (disconnect db)</font></div><div><font face="Courier New"> err-msg)))))</font></div><div><font face="Courier New"><br></font></div><div><font face="Courier New">(define-syntax-rule (boiler-plate body ...)</font></div><div><font face="Courier New"> (boiler-plate/thunk (λ () body ...)))</font></div><div><font face="Courier New"><br></font></div><div><font face="Courier New">(let ()</font></div><div><font face="Courier New"> (define err-msg</font></div><div><font face="Courier New"> (boiler-plate</font></div><div><font face="Courier New"> < body ... ></font></div><div><font face="Courier New"> ))</font></div><div><font face="Courier New"> ; err-msg needed here</font></div><div><font face="Courier New"> err-msg</font></div><div><font face="Courier New"> )</font></div></div><div><br></div><br><div><div>On Dec 8, 2014, at 6:45 PM, George Neuner <<a href="mailto:gneuner2@comcast.net">gneuner2@comcast.net</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite">Hi all,<br><br>This is more curiosity than a problem.<br><br>I am writing a web service which uses a database and there is a fair bit of boilerplate exception handling code which is needed in just about every servlet. It takes up a lot of page and indentation space in the source and just offends my sensibilities. I have created a macro to condense the visual, but I'm not entirely happy with it because of how it deals with interactions among the template, the body and the surrounding code.<br><br>As used inline, everything I am doing fits into the following pattern:<br><br> (let [<br> (err-msg #f)<br> ]<br><br> :<br><br> ; --- start boilerplate<br> (let/ec fail-network<br> (with-handlers [<br> (exn:fail:network?<br> (lambda (e)<br> (set! err-msg "database connection error")<br> (fail-network)))<br> ]<br> (let [<br> (db (connect-database))<br> ]<br><br> (let/ec fail-sql<br> (with-handlers [<br> (exn:fail:sql?<br> (lambda (e)<br> (let [(info (exn:fail:sql-info e))]<br> (set! err-msg (cdr (assoc 'message info)))<br> (fail-sql))))<br> ]<br><br> (call-with-transaction db<br> (lambda ()<br> :<br> < body ... ><br> :<br> )<br> #:isolation 'repeatable-read)<br><br> )<br><br> (disconnect db))<br><br> )))<br> ; --- end boilerplate<br><br><br> ; err-msg needed here<br><br> )<br><br><br>The problems, of course, are that "err-msg" is external to the boilerplate code, and "db" is internal to it. The exception handlers in the boilerplate need access to "err-msg" (or whatever the actual variable name might be) and code in the <body> needs to reference "db" which is only defined within the scope of the macro.<br><br>I've gotten it to work with syntax-rules by passing the problem names in as arguments:<br><br>(define-syntax with-database<br> (syntax-rules ()<br> ((with-database-connection db err-msg body ...)<br> ... )))<br><br>knowing that I can use any names externally or in the body (the above is just example).<br><br>This works, but having to pass in the (name of the) required error status variable is ugly. I know I can add a keyword (or several) to handle the status variable, but reasonable syntaxes for it are convoluted. Something like "with-database-connection <JOE> sending errors to <BOB> ..." obviously is possible, but is unwieldy (and un-Scheme-like [ un-Schemely? ] ) - it looks more like Smalltalk or Lisp's loop language than it does like Scheme. 8-)<br><br>I suppose I could require to pass in exception handler functions rather than a target for their output, but that also is unwieldy and error prone because the functions have to be inserted at different nesting levels.<br><br>Is there some idiomatic way people normally handle this kind of broken abstraction? I've searched a bit trying to find a discussion of something like this, but so far haven't found anything enlightening.<br><br>Thanks,<br>George<br><br><br>____________________<br> Racket Users list:<br> <a href="http://lists.racket-lang.org/users">http://lists.racket-lang.org/users</a><br></blockquote></div><br></body></html>