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?