[plt-scheme] Catch an unknown method error

From: Ryan Culpepper (ryanc at ccs.neu.edu)
Date: Thu Feb 21 08:43:06 EST 2008

Filipe Cabecinhas wrote:
> On 20 Feb, 2008, at 22:48, Matthias Felleisen wrote:
>> I recommend a macro for method calls:
>> (send <exp> <name> <exp1> ...)
>> -->
>> (with-handlers ((... (lambda (x) (printf "method not found ...") ...))
>>   (send:proper <exp> <name> <exp1> ...))
>> Then re-export new-send as send and write code as usual. -- Matthias

Catching the exception doesn't tell you whether the immediate 'send' 
referred to a non-existing method or if the method did exist but some 
other 'send' failed during the execution of the method.

Use 'method-in-interface?' and 'object-interface' instead to check the 
existence of the method before doing the call. Or use 
'object-method-arity-includes?' again if you also want to forward on 
arity mismatch.

Revised code below.

> So, I got something like this. At least in minor testing, it seems to 
> work. It's a bit ugly here and there (and throws an error for send/apply 
> instead of send).
> What I found out is that there are too few exceptions, which is one 
> thing Java got (partly?) right. The exn:fail:object exception doesn't 
> tell me exactly what went wrong so I had to go around and use a regexp. 
> Also I didn't do a macro for send/apply (and others) yet because I 
> haven't felt the need (if I do, it won't be much different from this one).
> code:

Here's my version:

(module test scheme/base
   (require (except-in scheme/class send))
   (provide send)

   (define-syntax send
     (syntax-rules ()
       [(_ exp name exp1 ...)
        (let ([obj exp]
              [args (list exp1 ...)])
          (if (and (not (method-in-interface? 'name (object-interface obj)))
                   (object-method-arity-includes? obj 'forward-invocation
                                                  (add1 (length args))))
                (printf "No such method: ~a for object ~a with args: ~a, 
                        'name obj args)
                (send/apply obj forward-invocation 'name args))
              (send/apply obj name args)))])))


>  > (require (except-in scheme/class send))
>   (require "test.scm")
>   (send (new object%) ola)
> . . test.scm:17:9: send/apply: no such method: ola for class: object%
>  > (define a% (class object% (super-new) (define/public 
> (forward-invocation name . args)
>                                           (printf "Method: ~a args: 
> ~a~%" name args))))
>   (send (new a%) hi)
> No such method: hi for object #(struct:object:a% ...) with args: (), 
> forwarding.
> Method: hi args: ()
>  >
> I'll test it better and integrate it tomorrow. If you have some comments 
> please tell me, I'm a CLer and haven't got around the whole hygienic 
> macro thing.
> F
> _________________________________________________
>  For list-related administrative tasks:
>  http://list.cs.brown.edu/mailman/listinfo/plt-scheme

Posted on the users mailing list.