Prev: faster?
Next: Article about lisp and array languages
From: Thomas A. Russ on 2 Nov 2009 18:15 mike <mpheasant(a)gmail.com> writes: > Thanks everyone for the different solutions. > In this case I wasnt clear enough that I'm writing something like an > awk script to reformat tab-delimited input, so need an actual tab. .... > In the end I guess my problem is just how to embed a tab char into the > format string using an 'escape sequence'. (Embedding the actual tab > char in the source isnt appealing.) This seems to work ok: Well, it may not be appealing to you, but inserting the literal character into the string is the easy Lisp Way(tm) to do it. It is just like when you want to have a literal newline character (sorry Pascal) in a constant string. The way you do that is to literally insert the newline character: (defvar *a-multi-line-string* "This is a string that extends over several lines in lisp.") (defvar *a-single-line-string* "This is a string\n on one line with odd\n characters in it.") -- Thomas A. Russ, USC/Information Sciences Institute
From: Kyle M on 2 Nov 2009 22:12 On Nov 2, 4:52 pm, mike <mpheas...(a)gmail.com> wrote: > Thanks everyone for the different solutions. > In this case I wasnt clear enough that I'm writing something like an > awk script to reformat tab-delimited input, so need an actual tab. > Thanks to Vassil for pointing out the different results from > (reduce ... (format nil ...)) and (reduce ... (format t ...)), I didnt > know that either. > > In the end I guess my problem is just how to embed a tab char into the > format string using an 'escape sequence'. (Embedding the actual tab > char in the source isnt appealing.) This seems to work ok: > > (format t (concatenate 'string "~{~a~^" (string #\Tab) "~}~%") '(1 2 > 3)) > > Otherwise the ~/ is a good way to go. > > I thought there would have been an easier way to insert control chars > into the format string; seems wierd that there is a special case for ~ > %, and that recognising codes like #\Tab wouldnt be in the spec. > > Cheers > > M > > On Nov 3, 4:48 am, Kyle M <kyle...(a)gmail.com> wrote: > > > On Nov 2, 1:29 pm, Carl Taylor <carltay...(a)att.net> wrote: > > > > On Nov 2, 2:00 am, mike <mpheas...(a)gmail.com> wrote: > > > > > Hi > > > > > Formatting a list as a comma-delimited string is easy; > > > > > (format nil "~{~a~^,~}" '(1 2 3)) => "1,2,3" > > > > > How do i do the same (SBCL) but with tab characters in the output? > > > > It must be simple but I've tried a ton of different things. > > > > Use the ~n@T directive in the format string where n is an integer > > > to specify the width of the desired tab. > > > > CL-USER 7 > (format nil "~{~a~^~5@T~}" '(1 2 3)) > > > "1 2 3" > > > > Carl Taylor > > > The ~T is not equivalent to #\Tab. But like Madhu said earlier, it > > depends on your editor. Some may treat #\Tab as just some number of > > spaces, so it wouldn't matter anyway. > > I think you've found a good way to do it using concatenate. For the record, there are all kinds of ways of doing this without using the ~ {~} format iteration, not just reduce like I initially suggested. It's terribly boring, and probably won't attract everyone, but having written a few files out, I'd rather go with what I consider to be simple: (format ostream "~A" (first list)) (dolist (x (rest list)) (format ostream "~C~A" #\tab x)) And then if you wanted that in string form you could wrap this guy around it. (with-output-to-string (ostream) ...) Kyle
From: Don Geddis on 2 Nov 2009 23:12 mike <mpheasant(a)gmail.com> wrote on Mon, 2 Nov 2009 : > In this case I wasnt clear enough that I'm writing something like an > awk script to reformat tab-delimited input, so need an actual tab. > (format t (concatenate 'string "~{~a~^" (string #\Tab) "~}~%") '(1 2 3)) Everything goes better with LOOP: (loop for first-time? = t then nil for element in '(1 2 3) unless first-time? do (format t "~A" #\tab) do (format t "~A" element) ) YMMV. More wordy than a constructed FORMAT string. But clearer? I suppose it depends on what you're used to, whether you spend more time with LOOP or with FORMAT control strings. (I suspect the final compiled code isn't all that different.) -- Don _______________________________________________________________________________ Don Geddis http://don.geddis.org/ don(a)geddis.org
From: John Thingstad on 9 Nov 2009 07:56
The Mon, 02 Nov 2009 10:48:18 -0800, Kyle M wrote: > On Nov 2, 1:29 pm, Carl Taylor <carltay...(a)att.net> wrote: >> On Nov 2, 2:00 am, mike <mpheas...(a)gmail.com> wrote: >> >> > Hi >> >> > Formatting a list as a comma-delimited string is easy; >> >> > (format nil "~{~a~^,~}" '(1 2 3)) => "1,2,3" >> >> > How do i do the same (SBCL) but with tab characters in the output? It >> > must be simple but I've tried a ton of different things. >> >> Use the ~n@T directive in the format string where n is an integer to >> specify the width of the desired tab. >> >> CL-USER 7 > (format nil "~{~a~^~5@T~}" '(1 2 3)) "1 2 3" >> >> Carl Taylor > > The ~T is not equivalent to #\Tab. But like Madhu said earlier, it > depends on your editor. Some may treat #\Tab as just some number of > spaces, so it wouldn't matter anyway. Another way is to modify the reader to accept \n \r \t etc.. as C does. From a printf function I wrote long ago.. (I think Gareth McCaughan originally suggested this.) (defvar *string-escape-character* #\\) (defvar *string-escape-table* ;; built with LIST and CONS so it's legal to modify it (list (cons #\t #\Tab) (cons #\n #\Newline) (cons #\r #\Return) ...)) (defvar *escaped-string-delimiters* (list #\" #\')) (set-dispatch-macro-character #\# #\E (lambda (stream sub-char infix-arg) (declare (ignore sub-char infix-arg)) (let ((delimiter (read-char stream)) (escaped nil)) (assert (member delimiter *escaped-string-delimiters*)) (coerce (loop for next-char = (read-char stream) nconc (cond (escaped (progn (setf escaped nil) (list (or (cdr (assoc next-char *string-escape-table*)) next-char)))) ((char= next-char delimiter) (loop-finish)) ((char= next-char *string-escape-character*) (setf escaped t) nil) (t (list next-char)))) 'string)))) (format nil #E"~{~a~^\t~}" '(1 2 3)) This would be better if you do this type of thing a lot.. Another way is to modify the reader to accept \n \r \t as C does. From a printf function I wrote long ago.. (I think Gareth McCaughan originally suggested this.) (defvar *string-escape-character* #\\) (defvar *string-escape-table* ;; built with LIST and CONS so it's legal to modify it (list (cons #\t #\Tab) (cons #\n #\Newline) (cons #\r #\Return) ...)) (defvar *escaped-string-delimiters* (list #\" #\')) (set-dispatch-macro-character #\# #\E (lambda (stream sub-char infix-arg) (declare (ignore sub-char infix-arg)) (let ((delimiter (read-char stream)) (escaped nil)) (assert (member delimiter *escaped-string-delimiters*)) (coerce (loop for next-char = (read-char stream) nconc (cond (escaped (progn (setf escaped nil) (list (or (cdr (assoc next-char *string-escape-table*)) next-char)))) ((char= next-char delimiter) (loop-finish)) ((char= next-char *string-escape-character*) (setf escaped t) nil) (t (list next-char)))) 'string)))) (format nil #E"~{~a~^\t~}" '(1 2 3)) This would be better if you do this type of thing a lot.. -- John Thingstad |