<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>