[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Alternative formulations of keywords



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