December 5 2006

 Whenever the system dispatches an event,the call to the handler procedure is wrapped so that
full continuation jumps are not allowed to escape from the dispatch, and escape continuation
jumps are blocked at the dispatch site.  The following block procedure illustrates how the system
blocks escape continuation jumps:

(define(block f)
;;calls f and returns void if f tries to escape
(let([done? #f])
  (let/ec k
    (dynamic-wind
      void
      (lambda()(begin0 (f) (set! done? #t)))
      (lambda()(unless done? (k (void))))))))

(block (lambda()5)); ⇒ 5
(let/ec k (block (lambda () (k 10)))); ⇒ void
(let/ec k ((lambda ()(k 10))) 11); ⇒ 10
(let/ec k (block (lambda ()(k 10))) 11); ⇒ 11

  The above four statements caused different results.  Let's look at why is it.  The first
statement is easy to understand.  To understand the result from the second statement, we must
study inside "block".  The main body of the "block" is to apply "dynamic-wind".  The middle
thunk in the "dynamic-wind" is to evaluate "f" and modify the flag "done?".  Before leaving
the "dynamic-wind", its third thunk must be invoked.  It check whether the "done?" is false,
if false, it will return (void) to the current continuation.  In other words, in that case
the "dynamic-wind" return a "void" value, its middle thunk was interruptted and no value was
returned.

  So, the flag "done?" is used to test whether the middle thunk of the "dynamic-wind" was blocked.
Now let us come back to the second statement.  Firstly, let's modify this statement as "(let/ec
k (lambda () (k 10)))", it means to return 10 to the continuation "k".  The second statemnet
was also going to do so.  Nevertheless, when jump out to the outer continuation "k", the
system stop it (stop the behavior of the middle thunk of the "dynamic-wind") at the point "(f)",
so that the consequent the modiying statement was not evaluated.  When leaving the "dynamic-wind",
the "unless" find that the "done?" is still false, so return "(void)" to the "block"'s
continuation.  Now I think you have understood why the result of the second statement is "void".

  Right!  Let's study the third statement.  As a matter of fact, it is so easy to understand in
that the "((lambda ()(k 10)))" return 10 to the outer continuation.  The forth statement is
similiar to the second, because to block the "((lambda ()(k 10)))" return 10 to the outer
continuation, no jump out the outer continuation, so the following statement -- 11 was evaluated.
The result of the whole forth statement was 11.

  Calls to the event dispatch handler are also protected with "block".

  This blocking of continuation jumps complicates the interaction between "with-handlers" and
"yield" (or the default event dispatch handler).  For example, in evaluating the expression

(with-handlers([(lambda(x) #t)
  (lambda(x) (error "error during yield"))])
 (yield))

the "error during yield" handleris never called, even if a call back procedure invoked by
yield raises an exception.  The "with-handlers" expression installs an exception handler
that tries to jump back to the context of the "with-handlers" expression before invoking a
handler procedure; this jump is blocked by the dispatch within "yield", so "error during yield"
is never printed.  Exceptions during yield are "handled" in the sense that control jumps out
of the event handler, but "yield" may dispatch another event rather than escaping or returning.

  The following expression demonstrates a more useful way to handle exceptions with in "yield":

(let/ec k
  (parameterize([current-exception-handler
  (lambda(x)
    (error"error during yield")
  (k))])
  (yield)))


  This expression installs an exception handler that prints an error message before trying to
escape.  Like the continuation escape associated with "with-handlers", the escape to k never
succeeds.  Nevertheless, if an exception is raised by "yield", an error message is printed
before control returns to the event dispatcher an event handler during the call to within "yield". 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值