From lpetit at sqli.com Tue Nov 28 13:26:40 2006 From: lpetit at sqli.com (Laurent PETIT) Date: Tue, 28 Nov 2006 14:26:40 +0100 Subject: [quiz] Enhanced Strings in CL ? Message-ID: 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, but first of all, will an ANSI compliant implementation let redefine the reader to alter the meaning of strings ? 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 : (format t "This returned string is an enhanced string and the value of x and y will be replaced 'a la ruby' : x=~a, y =~a") x y) thanks in advance for your answers, both on feasibility and/or complete answers to this "unofficial" quiz ;-) And oh, if I definitely bothered you by sending this message on the wrong list, please let me know what would be the most natural list/newsgroup to post this message on ? Thanks in advance, A lisp beginner, -- Laurent PETIT -------------- next part -------------- An HTML attachment was scrubbed... URL: From pjb at informatimago.com Tue Nov 28 19:19:00 2006 From: pjb at informatimago.com (Pascal Bourguignon) Date: Tue, 28 Nov 2006 20:19:00 +0100 Subject: [quiz] Enhanced Strings in CL ? In-Reply-To: References: Message-ID: <17772.35748.873792.797875@thalassa.informatimago.com> 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. From pjb at informatimago.com Tue Nov 28 19:23:16 2006 From: pjb at informatimago.com (Pascal Bourguignon) Date: Tue, 28 Nov 2006 20:23:16 +0100 Subject: [quiz] Enhanced Strings in CL ? In-Reply-To: <17772.35748.873792.797875@thalassa.informatimago.com> References: <17772.35748.873792.797875@thalassa.informatimago.com> Message-ID: <17772.36004.40961.195455@thalassa.informatimago.com> Pascal Bourguignon writes: > (defun parse-enhanced-string (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) There's a little problem with my function, it doesn't escape #\~ in the string. This is left as an exercise for the reader... (quote "~ ho ho ~ x=#{x} ~") --> (format nil "~~ ho ho ~~ x=~A ~~" x) -- __Pascal Bourguignon__ http://www.informatimago.com/ Litter box not here. You must have moved it again. I'll poop in the sink. From rosssd at gmail.com Tue Nov 28 23:50:40 2006 From: rosssd at gmail.com (Sean Ross) Date: Tue, 28 Nov 2006 23:50:40 +0000 Subject: [quiz] Enhanced Strings in CL ? In-Reply-To: References: Message-ID: <5bef28df0611281550t26e8bcf5mad8cd66e7d01d228@mail.gmail.com> I'd recommend downloading cl-interpol it should give you what you are looking for. CL-USER 2 > (cl-interpol:enable-interpol-syntax) CL-USER 3 > #?"1 is less than ${most-positive-fixnum}" "1 is less than 8388607" Cheers, Sean. -------------- next part -------------- An HTML attachment was scrubbed... URL: From lpetit at sqli.com Wed Nov 29 09:18:53 2006 From: lpetit at sqli.com (Laurent PETIT) Date: Wed, 29 Nov 2006 10:18:53 +0100 Subject: [quiz] Enhanced Strings in CL ? In-Reply-To: <17772.35748.873792.797875@thalassa.informatimago.com> References: <17772.35748.873792.797875@thalassa.informatimago.com> Message-ID: Hello, 2006/11/28, Pascal Bourguignon : > > [...] > No, it's trivial. Thank you very much for your answer, and even for the solution !! See also: http://www.cliki.net/cl-interpol Thanks for the link ! [...] > > > 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? Well, I'm not sure this one is ironic or serious ? ;-) I already know about Common Lisp Hyper Spec. Still not totally familiar with it, but making progress. What has blocked me was the fact that I didn't know if it was possible to override certain macro characters. Nevertheless, if you have instructions that would make me more productive while searching CLHS, I'll receive them with pleasure :-) -- Laurent -------------- next part -------------- An HTML attachment was scrubbed... URL: From pjb at informatimago.com Wed Nov 29 15:27:18 2006 From: pjb at informatimago.com (Pascal Bourguignon) Date: Wed, 29 Nov 2006 16:27:18 +0100 Subject: [quiz] Enhanced Strings in CL ? In-Reply-To: References: <17772.35748.873792.797875@thalassa.informatimago.com> Message-ID: <17773.42710.903079.877979@thalassa.informatimago.com> Laurent PETIT writes: > Hello, > > 2006/11/28, Pascal Bourguignon : > > > > [...] > > No, it's trivial. > > > Thank you very much for your answer, and even for the solution !! > > See also: http://www.cliki.net/cl-interpol > > > Thanks for the link ! > > [...] > > > > > 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? > > > Well, I'm not sure this one is ironic or serious ? ;-) > > I already know about Common Lisp Hyper Spec. Still not totally familiar with > it, but making progress. > > What has blocked me was the fact that I didn't know if it was possible to > override certain macro characters. Well, the pages about SET-MACRO-CHARACTER and SET-DISPATCH-MACRO-CHARACTER don't mention any restriction, so any character is game for macro character. > Nevertheless, if you have instructions that would make me more productive > while searching CLHS, I'll receive them with pleasure :-) Read the non-dictionnary parts to get background information, and use the _permuted_ _index_ to find all the relevant symbols: http://www.lispworks.com/documentation/HyperSpec/Front/X_Symbol.htm Here you could have found all the symbols containing CHARACTER and all the symbols containing MACRO, and therefore all the symbols about MACRO-CHARACTERs. Reading all these pages would let you know that you can override any character macro. -- __Pascal Bourguignon__ http://www.informatimago.com/ WARNING: This product warps space and time in its vicinity. From lpetit at sqli.com Wed Nov 29 21:10:42 2006 From: lpetit at sqli.com (Laurent PETIT) Date: Wed, 29 Nov 2006 22:10:42 +0100 Subject: [quiz] Enhanced Strings in CL ? In-Reply-To: <17772.35748.873792.797875@thalassa.informatimago.com> References: <17772.35748.873792.797875@thalassa.informatimago.com> Message-ID: Hello, I've modified the code as follows (also not yet corrected the tilde bug) : What you can see is that insted of restoring the full initial readtable, I only restore the #\" macro character previous function (the one I have overriden with (start). This way, I do not reset other -possible- personalized macro character functions. I also provide a (stop) method which restores the previous #\" macro character. I also twiked the main function in order to let the initial string unchanged in case no ${} is used (usefull for a lot of macros that only accept raw strings, such as defpackage, ...). Please let me know if you think this would not work in a case I haven't seen. The code follows : (defpackage "ENHANCED-STRINGS" (:USE "COMMON-LISP") (:EXPORT "START") (:EXPORT "STOP")) (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) (if (rest chunks) (return `(format nil ,(format nil "~{~A~^~~A~}" (nreverse chunks)) ,@(nreverse args)))) (return string)))) (defun reader-macro--enhanced-string (stream dblquote) (let ((*readtable* (copy-readtable))) (set-macro-character #\" (get-old-macro-character)) (unread-char dblquote stream) (parse-enhanced-string (read stream t nil t)))) (let ((old-macro-character nil)) (defun start () (unless old-macro-character (setf old-macro-character (get-macro-character #\")) (set-macro-character #\" #'reader-macro--enhanced-string))) (defun stop () (when old-macro-character (set-macro-character #\" old-macro-character) (setf old-macro-character nil))) (defun get-old-macro-character () old-macro-character)) -------------- next part -------------- An HTML attachment was scrubbed... URL: From pjb at informatimago.com Wed Nov 29 22:23:01 2006 From: pjb at informatimago.com (Pascal Bourguignon) Date: Wed, 29 Nov 2006 23:23:01 +0100 Subject: [quiz] Enhanced Strings in CL ? In-Reply-To: References: <17772.35748.873792.797875@thalassa.informatimago.com> Message-ID: <17774.2117.451517.379513@thalassa.informatimago.com> Laurent PETIT writes: > Hello, > > I've modified the code as follows (also not yet corrected the tilde bug) : > What you can see is that insted of restoring the full initial readtable, I > only restore the #\" macro character previous function (the one I have > overriden with (start). This way, I do not reset other -possible- > personalized macro character functions. > I also provide a (stop) method which restores the previous #\" macro > character. > > I also twiked the main function in order to let the initial string unchanged > in case no ${} is used (usefull for a lot of macros that only accept raw > strings, such as defpackage, ...). > > Please let me know if you think this would not work in a case I haven't > seen. Well, what hasn't been explicitely mentionned, is that any usage of a string where it's _not_ evaluated (which may be a lot, including the macros), wouldn't work anymore. What if I want to name my package: "PACK${1}" ? Macros can expand strings given as argument as (quote "string") instead of merely "string". Compare the two results: (let ((x 1)) (values (quote "STR ${x}") "STR ${x}")) That's why cl-interpolate doesn't use the standard macro character, because we want to be able to write both true _literal_ string and interpolated strings. -- __Pascal Bourguignon__ http://www.informatimago.com/ "What is this talk of "release"? Klingons do not make software "releases". Our software "escapes" leaving a bloody trail of designers and quality assurance people in its wake."