[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