[plt-scheme] Reflection in class.ss
> 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!