[plt-scheme] Reflection in class.ss

From: Daniel Yoo (dyoo at cs.wpi.edu)
Date: Wed Mar 28 12:49:30 EDT 2007


> I'm trying to get the value of an object's field given the field's name. 
> The OO system (class.ss) provides get-field, but the field name is not 
> evaluated, and so must be a literal.  This is not sufficient use -- I 
> have a list of names and want to lookup the value at runtime.  Can this 
> be done?  If not, can the OO system be extended to support it?  This 
> kind of metaprogramming is useful for a great many cases.

Hi Noel,

If you can use accessor methods to get at those fields, then you can use 
the following:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   ;; call-accessor: object symbol -> any
   ;; Calls a 0-arity method whose name is determined at
   ;; runtime.
   (define (call-accessor object accessor-name)
     (define f (make-generic (object-interface object) accessor-name))
     (send-generic object f))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


If you have the ability to inspect the object, then the following may be 
what you're looking for:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(module get-field-at-runtime mzscheme
   (require (lib "class.ss")
            (only (lib "1.ss" "srfi") list-index))


   ;; get-runtime-field: object symbol -> any
   ;; Tries to get the field value from the object.
   ;; We must be able to inspect the class, or else this fails.
   (define (get-runtime-field obj name)
     (let*-values ([(class skipped) (object-info obj)]
                   [(name-symbol
                     field-k
                     field-name-list
                     field-accessor-proc
                     field-mutator-proc
                     super-class
                     skipped)
                    (class-info class)])
       (field-accessor-proc obj
                            (list-index (lambda (x)
                                          (eq? x name))
                                        field-name-list))))
   ;; example usage:
   (define c%
     (class object%
       (init-field name)
       (inspect #f)
       (super-new)))
   (define obj (new c% [name "Noel"]))

   (define (test)
     (display (get-runtime-field obj 'name))
     (newline)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


Best of wishes!


Posted on the users mailing list.