[Openmcl-devel] square bracket list
Pascal J. Bourguignon
pjb at informatimago.com
Sun Jul 24 04:46:18 PDT 2011
Taoufik Dachraoui <dachraoui.taoufik at gmail.com> writes:
> On Sun, Jul 24, 2011 at 11:56 AM, Taoufik Dachraoui
> <dachraoui.taoufik at gmail.com> wrote:
>> Hi
>>
>> is it possible to print special lists using square brackets
>>
>> example:
>>
>> (a b [1 2 3] e)
>>
>> the list [1 2 3] is special and is printed using a square bracket.
>>
>> I can cons a special character to differentiate special lists like the
>> following:
>>
>> (a b (#\$ 1 2 3) e)
>>
>> but it is better if i can find a way to print special lists using
>> square brackets.
>
> to be more precise, is there a way to print lists depending on the car
> of the list
> (cond
> ((eq (car lst) #\[) (print list using [...]))
> ((eq (car lst) #\{) (print list using {...}))
> (t (print list using (...))))
AFAIK, it is not possible, with the standard printer and print-object
generic function.
The problem is that you're not allowed by 11.1.2.1.2 point 19. to define
a method of print-object on the standard class CONS.
Furthermore, PRINT may just NOT call PRINT-OBJECT on standard types.
Therefore the only conforming solution you have is to define your own
printing function and/or your own printing generic function and methods.
Beware that you are not allowed to call directly PRINT-OBJECT yourself!
(defgeneric my-special-print (object stream)
;; BUG: Doesn't handle circular structures!
;; See "4.3.7 Integrating Types and Classes" for the classes you can use.
(:method ((object bit-vector) stream)
;; bit-vectors are vectors, but they cannot contain special lists.
(prin1 object stream))
(:method ((object string) stream)
;; strings are vectors, but they cannot contain special lists.
(prin1 object stream))
(:method ((object vector) stream)
(princ "#(" stream)
(when (plusp (length object))
(my-special-print (aref object 0) stream))
(loop :for i :from 1 :below (length object)
:do (princ " " stream)
(my-special-print (aref object i) stream))
(princ ")" stream)
object)
(:method ((object array) stream)
;; have fun, implementing multi-dimensional array printing.
object)
(:method ((object hash-table) stream)
;; some implementations can print the hash-table contents
;; perhaps you'll want to do so you too.
object)
(:method ((object cons) stream)
(flet ((print-list (start list end stream)
(princ start stream)
(when list
(my-special-print (car list) stream)
(loop
:for cell = (cdr list) :then (cdr cell)
:do (princ " " stream)
(my-special-print (car cell) stream)
(cond
((null (cdr cell))
(loop-finish))
((atom (cdr cell))
(princ " . " stream)
(my-special-print (cdr cell) stream)
(loop-finish)))))
(princ end stream)))
(cond
((eql (car object) #\[) (print-list #\[ (cdr object) #\] stream))
((eql (car object) #\{) (print-list #\{ (cdr object) #\} stream))
(t (print-list #\( object #\) stream))))
object)
(:method ((object t) stream)
(prin1 object stream)))
CL-USER> (my-special-print #((a b (#\{ c d) (#\[ e f)) 42 "Hello" (g h i) (#\{ k l (#\{ c d) (#\[ e f) m n)) *standard-output*)
#((A B {C D} [E F]) 42 "Hello" (G H I) {K L {C D} [E F] M N})
#((A B (#\{ C D) (#\[ E F)) 42 "Hello" (G H I) (#\{ K L (#\{ C D) (#\[ E F) M N))
Of course if you need a REPL to use my-special-print instead of print,
you can write your own REPL.
See for example: http://paste.lisp.org/display/18280
http://www.lispworks.com/documentation/HyperSpec/Body/11_abab.htm
http://www.lispworks.com/documentation/HyperSpec/Body/f_pr_obj.htm#print-object
--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
More information about the Openmcl-devel
mailing list