[quiz] Enhanced Strings in CL ?

Pascal Bourguignon pjb at informatimago.com
Tue Nov 28 19:19:00 UTC 2006


Laurent PETIT writes:
> Hello Quizzers,
> 
> I'm a newbie in Lisp (have already finished the ANSI Common Lisp book, made
> some tries with programming as well, and I'm searching the answer to this
> question I have : could it be possible to "enhance" the reader in order to
> have in lisp "enhanced strings".
> 
> That is : by just doing something once at the beginning of a lisp file (some
> call, ...), being able to have all the strings replaced by another string
> (or another form).
> 
> Something like this :
> 
> ;;; beginning of file
> 
> (enhanced-strings:start)
> 
> ...
> ...
> 
> (defun some-function (x y)
>    "This returned string is an enhanced string and the value of x and y will
> be replaced 'a la ruby' : x=${x}, y =${y}")
> 
> You see what I mean ....
> 
> This could be an interesting quiz, 

No, it's trivial.

(defpackage "ENHANCED-STRINGS"
  (:USE "COMMON-LISP")
  (:EXPORT "START"))

(in-package  "ENHANCED-STRINGS")

(defun parse-enhanced-string (string)
  (loop
     :with chunks = '()
     :with args = '()
     :with start = 0
     :for pos = (search "${" string :start2 start)
     :for end = (and pos (search "}" string :start2 pos))
     :while end
     :do (progn
           (push (subseq string start pos) chunks)
           (multiple-value-bind (form next)
               (read-from-string string t nil :start (+ 2 pos) :end end)
             (loop :while (and (< next end)
                               (member (aref string next) '(#\space #\newline)))
                :do (incf next))
             (unless (= next end)
               (error "Junk in ~S" (subseq string pos end)))
             (push form args))
           (setf start (1+ end)))
     :finally (progn
                (push (subseq string start) chunks)
                (return (cons (format nil "~{~A~^~~A~}" (nreverse chunks))
                              (nreverse args))))))

(defun reader-macro--enhanced-string (stream dblquote)
  (let ((*readtable* (copy-readtable nil)))
    (unread-char dblquote stream)
    `(format nil ,@(parse-enhanced-string (read stream t nil t)))))

(defun start ()
  (set-macro-character #\" (function reader-macro--enhanced-string)))



(start)
'"This returned string is an enhanced string and the value of x and y will
be replaced 'a la ruby' : x=${(* 42 x)}, y =${y}"
-->
(format nil
  "This returned string is an enhanced string and the value of x and y will
be replaced 'a la ruby' : x=~A, y =~A"
  (* 42 x) y)


See also: http://www.cliki.net/cl-interpol


> but first of all, will an ANSI compliant
> implementation let redefine the reader to alter the meaning of strings ?

Yes. 

 
> I know I can add macro characters, play with macro character dispatching
> functions, ... but what about "overriding" the reader to intercept strings
> and change them, as for the above example, with :

What about SET-MACRO-CHARACTER and SET-DISPATCH-MACRO-CHARACTER ?
Do you need instructions on how to search CLHS?


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Litter box not here.
You must have moved it again.
I'll poop in the sink. 



More information about the Quiz mailing list