Hi Gustavo,
I'm going to have to spend some quality time studying syntax-case. I'm
not really fluent, but I think I understand what you're doing. I like
that it is able to encapsulate the connection ("db") variable while
still making it available in the scope of the body.
The only issue then is that the user is locked into using the name used
in the macro. No perfect solutions 8-)
Thanks,
George
On 12/9/2014 7:40 AM, Gustavo Massaccesi wrote:
I think that you want to capture the variables. I made a simplified
example. The other variables (for example "hidden") are not capture,
as usual.
;--- boilerplate.rkt ---
#lang racket
(define (call-with-?? proc) (proc)); just for the example
(define exn:fail:network? exn:fail?); just for the example
(provide with-db)
(define-syntax with-db
(lambda (stx)
(syntax-case stx ()
[(_ body ...)
(with-syntax ([err-msg (datum->syntax stx 'err-msg stx stx)]
[db (datum->syntax stx 'db stx stx)])
; --- start boilerplate
(syntax-protect
(syntax/loc stx
(let/ec fail-network
(with-handlers [(exn:fail:network? (lambda (e)
(set! err-msg
"database connection error")
(fail-network)))]
(define db 5)
(define hidden 7)
(call-with-?? (lambda () body ...))))))
; --- end boilerplate
)])))
;--- main.rkt
#lang racket
(require "boilerplate.rkt")
(define err-msg #f)
(define hidden "BU")
(with-db
(displayln db); ==> 5
(displayln hidden); ==> "BU"
(/ 1 0)
(display "never"))
(when err-msg
(error 'error err-msg))
;-------
There is a big red warning in the Racket documentation about macros
with variable capture, but I can't find it. It recommends to use
syntax-parameters, but the syntax parameter can't change the value of
err-msg after the macro body had finished. The problem is that if you
use the with-db macro inside a with-super-db macro, the results are
strange.
Gustavo
____________________
Racket Users list:
http://lists.racket-lang.org/users