[plt-scheme] Re: Novice question: evaluating symbols

From: Carl Eastlund (cce at ccs.neu.edu)
Date: Fri Jan 8 10:10:01 EST 2010

On Fri, Jan 8, 2010 at 8:55 AM,  <mike at goblin.punk.net> wrote:
>
> Thank you for the explanation.  At the time, I was just
> exploring what I could do with Scheme.  I am still trying to
> think Scheme-ishly.  I haven't learned macros yet, but maybe
> that should move up on my agenda.
>
> Scheme seems to have more levels of indirection than what I'm
> used to.  Returning to my (contrived) problem, how might I force
> the evaluation of a symbol?  For example, the apply expression
> below will evaluate date-year and then apply the procedure to
> a-date, but the subsequent map expression will get the symbol
> 'date-year and try to apply that to a-date.
>
> Or is this approach a dead end in Scheme?
>
> (define selectors
>  (map (λ (a-symbol) (string->symbol (string-append "date-" (symbol->string a-symbol))))
>       '(year
>         month
>         day
>         week-day
>         hour
>         minute
>         second)))
>
> (apply date-year (list a-date))
>
> (map (λ (x) (apply x (list a-date)))
>     selectors)
>
> Thanks again,
> MJG
>
> P.S.  I've changed my subscription details to try to avoid
> triggering the spam filter.

Definitely time to move macros up on your agenda.  Evaluating a
run-time symbol to a run-time function is tricky... it's really no
easier than evaluating a run-time number to a run-time function.
Run-time symbols are just symbols, they don't have another meaning.

Compile-time symbols, on the other hand, are used as variable names in
compiled code.  They can easily correspond to run-time functions:

(define (f x) (+ x 1))
f ;; <-- compile-time symbol, run-time function

Macros let you compute with compile-time symbols and construct
variables, so they let you play games like the renaming you want to
do.

Here's some freebie code:

--------------------------------------------------

#lang scheme

;; define a macro for binding one shorthand:
(define-syntax (define-shorthand stx)

  ;; helper function for tedious conversion of compile-time datatypes...
  (define (combine-variable-names prefix suffix)
    (datum->syntax ;; from symbol to variable name
     stx
     (string->symbol ;; from string to symbol
      (string-append ;; combine strings
       (symbol->string (syntax-e prefix)) ;; from variable name to
symbol to string
       "-"
       (symbol->string (syntax-e suffix))))))

  ;; here's the meat of the macro:
  (syntax-case stx ()
    [(define-shorthand prefix suffix) ;; pull apart the macro's inputs
     (with-syntax ([long (combine-variable-names #'prefix #'suffix)])
;; combine the names
       #'(define suffix long))])) ;; construct the resulting definition

;; define another macro for several shorthands at once:
(define-syntax-rule (define-shorthands prefix [suffix ...])
  (begin (define-shorthand prefix suffix) ...))

;; now try it out:
(define-shorthands date [year month day week-day hour minute second])

(define now (seconds->date (current-seconds)))

(year now)
(month now)
(day now)
(week-day now)
(hour now)
(minute now)
(second now)

--------------------------------------------------

This is not a particularly easy macro to write.  It turns out
combining multiple variable names (such as date + year = date-year) is
a bit tedious, and not supported in the simplest form of macros.  The
simple ones just shuffle around existing names, without creating new
ones.  Still, it's an alternative to using eval, and maybe a starting
point for finding out more about macros.

Good luck and happy Scheming!

--Carl


Posted on the users mailing list.