[plt-scheme] exception in local variable access from augmented method

From: Dimitris Vyzovitis (vyzo at media.mit.edu)
Date: Sat Dec 6 12:42:10 EST 2008

On Sat, 6 Dec 2008, Matthew Flatt wrote:

> At Fri, 5 Dec 2008 00:07:51 -0500 (EST), Dimitris Vyzovitis wrote:
>> I am trying to mutate a local variable from an augmented method, but all I
>> get is a horrible exception. Here is an example:
>> (define Frame%
>>    (class frame%
>>      (define foo 0)
>>      (define (can-close?)
>>        (printf "~a~n" foo)
>>        (set! foo (add1 foo))
>>        #t)
>>      (augment can-close?)
>>      (super-new)))
>> (define xx (new Frame% (label "Foo") (width 300) (height 300)))
>> (send xx show #t)
>> (yield 'wait)
>> <click>
>> 0
>> procedure application: expected procedure, given: 0; arguments were: 0 1
> I haven't been able to get that error when running the code above,
> either under Mac OS X or X11. I put "#lang scheme/gui" at the beginning
> of the code and tried running in both DrScheme (Module language) and
> MrEd. I'm assuming that "<click>" means clicking to close the frame.

yes. I am running with 'mred -iqz', X11

> Is there more to the program or a different way I should run it?

Aha, there is: there was a set! replacement that was loaded that I forgot 
was there. The said set! replacement does expand to the built-in set! 
(of course) and in general has worked for me as expected -- expect when 
I try to mutate local variables inside lifted class methods (it happens 
with override as well, not just augment).

So, after some digging, the problem is coming from the set!-transformer 
expansion; here is a distilled version that triggers the problem:

(module test scheme/base
   (require (for-syntax scheme/base))
   (provide (rename-out (~set! set!)))
   (define-syntax (~set! stx)
     (syntax-case stx ()
       ((_ tgt v)
        (and (identifier? #'tgt)
             (set!-transformer? (syntax-local-value #'tgt (lambda () #f))))
        ((set!-transformer-procedure (syntax-local-value #'tgt)) stx))
       ((_ tgt v)
        (datum->syntax stx (syntax-e #'(set! tgt v)))))))

(require 'test)

(define Frame% ...) ; as before
(define xx (new Frame% (label "Foo") (width 300) (height 300)))
(send xx show #t)
(yield 'wait)

<click> ; close the window
procedure application: expected procedure, given: 0; arguments were: 0 1

It seems the culprit here is the set! renaming breaking the transformer 
syntax-id-rules (they match with free-identifier=?, don't they?)

-- vyzo

Posted on the users mailing list.