Newsgroups: comp.lang.scheme
Path: cantaloupe.srv.cs.cmu.edu!das-news2.harvard.edu!news2.near.net!howland.reston.ans.net!Germany.EU.net!ieunet!tcdcs!news.tcd.ie!bosullvn
From: bosullvn@tcd.ie (Bryan O'Sullivan)
Subject: Re: nesting quasiquotes
Message-ID: <D10x2o.CzL@news.tcd.ie>
Sender: usenet@news.tcd.ie (TCD News System )
Organization: Plus Crimethinkers Inc.
References: <derf-181294142059@tonto-slip3.cis.brown.edu>
Date: Sun, 18 Dec 1994 20:32:48 GMT
Lines: 66

derf@brown.edu (Neil "Fred" Picciotto) writes:

>I am wondering why this is useful.  Can anyone give an example which
>demonstrates not only what the functionality is, but which demonstrates a
>reason why one would want to do this?

Here's a chunk of code I wrote the other day which implements a sort of
keyword argument facility not hugely dissimilar to that provided by
Common Lisp.  It assumes your Scheme interpreter has first-class
defmacros (which many do) and a "traditional" eval (taking one
argument, again common). 

(define (keyword->symbol keyword)
  (if (symbol? keyword)
      (let* ((key-string (symbol->string keyword))
	     (colon-index (- (string-length key-string) 1)))
	(if (char=? (string-ref key-string colon-index) #\:)
	    (string->symbol (substring key-string 0 colon-index))
	    (error "keyword name does not end in colon --" keyword)))
      (error "keyword is not a symbol --" keyword)))

(define (list->alist list car-transformer cdr-transformer)
  (if (even? (length list))
      (let loop ((list list)
		 (acc '()))
	(if (null? list)
	    (reverse acc)
	    (let ((key (car-transformer (car list)))
		  (value (cdr-transformer (cadr list))))
	      (loop (cddr list)
		    (cons (cons key value) acc)))))
      (error "keyword list must be even in length --" list)))

(defmacro define-with-keywords (formals . body)
  `(define ,(car formals)
     (let ((defaults ',(list->alist (cdr formals) keyword->symbol eval)))
       (defmacro foo arglist
	 (let ((givens (list->alist arglist
				    (lambda (key)
				      (let ((symbol (keyword->symbol key)))
					(if (assoc symbol defaults)
					    symbol
					    (error "undefined keyword --"
						   symbol))))
				    (lambda (_) _))))
	   `(let ,(map (lambda (pair)
			 (let* ((key (car pair))
				(given (assoc key givens)))
			   `(,key ,(cdr (if given given pair)))))
		       defaults)
	      ,@',body)))
       foo)))

To answer your question about why anyone might want multiple levels of
unquoting, note the use of unquote-splicing after quote after unquote
towards the end of define-with-keywords above; this prevents the body
of the "function" being defined from being evaluated at definition time
(which you don't want).

	<b

--
Let us pray:
What a Great System.
Please Do Not Crash.
^D
