Re: Alternative formulations of keywords Marc Feeley 12 Apr 2006 04:54 UTC

On 11-Apr-06, at 10:54 PM, John Cowan wrote:

> What are the use cases for computed keywords?

Here are a few use cases.

1) You want to write a trace facility to help show the function calls
and returns that are performed.  On entry you want to print the
arguments of the function and the result on exit.  So you write this
higher order function:

(define (trace name f)
   (lambda args
     (write (cons name args))
     (newline)
     (let ((result (apply f args)))
       (write result)
       (newline)
       result)))

and use it like this:

(define (foo x #!key (y 11) (z 22))
   (+ x y z))

(set! foo (trace 'foo foo)) ; start tracing foo

(foo 1 z: 2)    will print:   (foo 1 z: 2)
                               14

2) You just got hold of this nice graphics library which has many
functions accepting named optional parameters:

(define (text str #!key (size 10) (color 'black)) ...)
(define (rect x y #!key (width 10) (height 10) (color 'red)) ...)

You want your students to use it for their next homework.
Unfortunately your students are french and don't know english too
well so you would like to translate the keywords into french to make
the code easier to read.  With computed keywords you get a modular
solution:

(define french-to-english
   '((taille:  . size:)
     (largeur: . width:)
     (hauteur: . height:)
     (append:  . concatener:)
     (creer:   . create:)
     (couleur: . color:)))

(define (make-translator dict)
   (lambda (x)
     (let ((y (assoc x dict)))
       (if y (cdr y) x))))

(define translator (make-translator french-to-english))

(define (translate-args args)
   (if (null? args)
       '()
       (cons (translator (car args))
             (cons (cadr args)
                   (translate-args (cddr args))))))

(define (translate0 f)
   (lambda args (apply f (translate-args args))))

(define (translate1 f)
   (lambda (a . args) (apply f a (translate-args args))))

(define (translate2 f)
   (lambda (a b . args) (apply f a b (translate-args args))))

(define (translate3 f)
   (lambda (a b c . args) (apply f a b c (translate-args args))))

With these functions you can then do:

(set! text (translate1 text))
(set! rect (translate2 rect))

(rect 100 200 largeur: 300)

The same code could be used to implement synonyms for the named
parameters (for example a long name and an abbreviation).

Marc