[racket] Dynamically calling struct accessors/method names
On Sep 6, 2011, at 2:44 PM, Todd Bittner wrote:
> Actually, on pondering it for a few more minutes, your original solution is sufficient for what I'm trying to do, which is to consolidate a lot of similar code into one common parent function, but it would be interesting to know how to call the function if I only had a string.
Good.
> So, if for argument's sake, I had a file with a list of approved functions and one of them were 'posn-x', how would I take "posn-x" the string and turn into posn-x, the accessor call (or function call if it weren't a struct)?
Here are three solutions, which I would use in the order v0, v1, and defined select:
#lang racket
(struct posn (x y) #:transparent)
(define in
(open-input-string (string-append "posn-" (if (< (random 100) 50) "x" "y"))))
;; case next protects me from someone sending me a bad command
(define (select.v0 in)
(define next (read in))
(case next
[(posn-x) posn-x]
[(posn-y) posn-y]
[else (error 'select "attack!")]))
;; but if there are lots of commands and I need some speed, I'd create a hash table and associate symbols and functions
(define (select.v1 in)
"use some hash table")
;; if all of this fails, I may fall back on eval but only with trepidation
(define-namespace-anchor top)
(define (select in)
(eval (read in) (namespace-anchor->namespace top)))
;; test it all
(define (foo a-posn a-selector)
(a-selector a-posn))
(foo (posn 3 4) (select in))