From: Christophe Turle
Subject: Re: mv quasi-quotation
Date: 
Message-ID: <41f95c05$0$2257$636a15ce@news.free.fr>
Christophe Turle wrote:
> is there a multiple-value quasi-quotation somewhere ?
>
> like :
>
> `(a ,(values 'x) b)    =>  (a x b)
> `(a ,(values) b)       =>  (a b)
> `(a ,(values 'x 'y) b) =>  (a x y b)
>
>
> Even a Clisp specific implementation.

Here are the pieces for a CLISP-specific implementation. Hope Google
Groups Beta doesn't munge the formatting.

It would be a lot simpler if you could live without the comma; in other
words $X rather than ,$X. But in some ways this is better because it
doesn't conflict with custom readers for the $ character.

As you can see the problem with this is that the , reader is
pervasively active. CLISP's usual reader knows when it's in a backquote
context, and so it can throw error messages otherwise. That logic is
not duplicated here in the wrapping reader, so the ,$ translation
happens anywhere.

One sneaky way to get the error handling would be to always call the
built-in reader, and then post-filter its output. How? You peek at the
next character, as is done now. If it's a dollar sign, then you swallow
it. Call the old reader, which will produce an unquote. Rip apart the
unquote, and convert it to the MULTIPLE-VALUE-LIST form and return
that.

Then, one finishing touch: check for the ,·@FORM case, for which you
can signal some error. After eating the $ character, peek to see
whether there is a @ character before calling the old comma reader.


;;;
;;; CLISP-specific hack to enable ,$ syntax in backquotes.
;;; This syntax splices multiple values. In other words,
;;;
;;; `(... ,$FORM ..)
;;;
;;; behaves like
;;;
;;; `(... ,@(multiple-value-list FORM) ...)
;;;
;;; Kaz Kylheku <···@ashi.footprints.net>
;;; January 25, 2005
;;;

(defvar *old-comma-reader* nil)

(defun new-comma-reader (stream character)
(let ((next-char (peek-char t stream)))
(if (char= next-char #\$)
(progn
(read-char stream)
(list 'multiple-value-list (read stream)))
(funcall *old-comma-reader* stream character))))

(defun install-hack ()
(unless *old-comma-reader*
(setf *old-comma-reader* (get-macro-character #\,))
(set-macro-character #\, #'new-comma-reader)))

(defun uninstall-hack ()
(when *old-comma-reader*
(set-macro-character #\, *old-comma-reader*)
(setf *old-comma-reader* nil)))


It doesn't seem to work. Here the tests :

CL-USER> `(a ,$(values 'x) b)
(A (MULTIPLE-VALUE-LIST (VALUES 'X)) B)

CL-USER> `(a ,$(values) b)
(A (MULTIPLE-VALUE-LIST (VALUES)) B)

CL-USER> `(a ,$(values 'x 'y) b)
(A (MULTIPLE-VALUE-LIST (VALUES 'X 'Y)) B)



-- 
___________________________________________________________
Christophe Turle.
sava preview http://perso.wanadoo.fr/turle/lisp/sava.html
(format nil ···@~a.~a" 'c.turle 'wanadoo 'fr) 
From: Kaz Kylheku
Subject: Re: mv quasi-quotation
Date: 
Message-ID: <1106875829.234267.262270@f14g2000cwb.googlegroups.com>
Christophe Turle wrote:
>
> It doesn't seem to work. Here the tests :
>
> CL-USER> `(a ,$(values 'x) b)
> (A (MULTIPLE-VALUE-LIST (VALUES 'X)) B)
>
> CL-USER> `(a ,$(values) b)
> (A (MULTIPLE-VALUE-LIST (VALUES)) B)
>
> CL-USER> `(a ,$(values 'x 'y) b)
> (A (MULTIPLE-VALUE-LIST (VALUES 'X 'Y)) B)

Aha, try this version. The code I posted is missing the splicing
unquote syntax around the (MULTIPLE-VALUE-LIST ...) form; the reader
should return

(SYSTEM::SPLICE (MULTIPLE-VALUE-LIST ...))

The corrected function is:

.(defun new-comma-reader (stream character)
.  (let ((next-char (peek-char T stream)))
.    (if (char= next-char #\$)
.      (progn
.	(read-char stream)
.	(list 'system::splice (list 'multiple-value-list (read stream))))
.      (funcall *old-comma-reader* stream character))))