[plt-scheme] An interface wrapper using macros and interface->method-names

From: Matthias Felleisen (matthias at ccs.neu.edu)
Date: Wed Jun 2 22:08:00 EDT 2004

On Jun 2, 2004, at 8:54 PM, Matthias Felleisen wrote:

>  For list-related administrative tasks:
>  http://list.cs.brown.edu/mailman/listinfo/plt-scheme
>
>
> On Jun 2, 2004, at 6:05 PM, David Stigant wrote:
>
>> I've been trying to write a macro which will take an interface and 
>> create a class which forwards all calls to the interface's methods on 
>> to another implementation of that interface.  For example, given this 
>> interface:
>>  
>> (define ifoo<%> (interface () foo bar baz))
>
> The above defines ifoo<%> to be a run-time value of kind interface.
>
>>  I want my macro
>>  
>> (wrap ifoo<%>)
>
> This is trying to use a value, which doesn't exist yet, to create a 
> piece of syntax. Once this piece of syntax is compiled and run will 
> produce a value that co-exists with ifoo<%>.
>
>
> You can turn interfaces into quasi-syntactic things and simultaneously 
> create wrappers:
>
> (require-for-syntax (lib "class.ss"))
>
> (define-syntax (define-interface stx)
>   (syntax-case stx ()
>     [(_ iname (super-name ...) name ...)
>      (let ([iname-wraped
>             (datum->syntax-object
>              #'iname
>              (string->symbol
>               (string-append (symbol->string (syntax-e (syntax 
> iname))) "-wrapped")))])
>        #`(define-values (iname #,iname-wraped)
>            (let* ([ii (interface (super-name ...) name ...)]
>                   [cc (class* object% (ii)
>                         (super-new)
>                         (init-field (implementation #f))
>                         (define/public (switch-implementation i)
>                           ;; after some basic checks
>                           (set! implementation i))
>                         (define/public name (lambda (x) (send 
> implementation name x)))
>                         ...)])
>              (values ii cc))))]))
>
> (define-interface ifoo () foo bar baz)
>
> (define mumble (class object% (super-new) (define/public (foo x) 10)))
>
> (define fake (new ifoo-wrapped (implementation (new mumble))))
>
> (send fake foo 22)
>
> ; (send fake moo 33)
>
> NOTE: I don't understand why the class* inside the macro doesn't 
> signal an error for not satisfying the interface.
>


Apologies, it's obvious :-) -- Matthias, old and tired

(require-for-syntax (lib "class.ss"))

(define-syntax (define-interface stx)
   (syntax-case stx ()
     [(_ iname (super-name ...) name ...)
      (let ([iname-wrapped
             (datum->syntax-object
              #'iname
              (string->symbol
               (string-append (symbol->string (syntax-e (syntax iname))) 
"-wrapped")))])
        #`(define-values (iname #,iname-wrapped)
            (let* ([ii (interface (super-name ...) name ...)]
                   [cc (class* object% (ii) (init implementation)
                         (super-new)
                         (define (check-ii> i)
                           (if (and (object? i) (is-a? i ii))
                               i
                               (error '#,iname-wrapped "~e does not 
implement ~s" i iname)))
                         (field (the-implementation (check-ii> 
implementation)))
                         (define/public (switch-implementation i)
                           (set! the-implementation (check-ii> i)))
                         (define/public name (lambda (x) (send 
the-implementation name x)))
                         ...)])
              (values ii cc))))]))

(define-interface ifoo () foo bar baz)

(define mumble (class object% (super-new) (define/public (foo x) 10)))

(define fake (new ifoo-wrapped (implementation (new mumble))))

(send fake foo 22)

(send fake bar 33)


Posted on the users mailing list.