From: Mirko
Subject: matrix -> nested list
Date: 
Message-ID: <3c623c4c-4a5d-433c-814a-1a7ee94808c9@j12g2000vbl.googlegroups.com>
I am converting matrices to nested lists in order to print their
contents using format's looping ~{, ~} directives.  For the
convernsion, I am using the following code that I adapted from a post
by Pascal Bourgignon

(let ((arr (make-array '(3 2) :initial-contents '((1 2) (3 4) (5
6)))))
  (loop
     with element-type = (array-element-type arr)
     with c-rows =  (array-dimension arr 1)
     with c-cols = (array-dimension arr 0)
     for i0 :from 0 :below c-cols
     for row = (make-array c-rows
			   :displaced-to arr
			   :displaced-index-offset (* i0 c-rows)
			   :element-type element-type)
     collect (coerce row 'list)))

Is there a better built-in lisp way to do the conversion, to print
arrays?   I guess I am reinventing the wheel (which is kind of fun),
but I could not find the original wheel.

Thank you,

Mirko

From: Pillsy
Subject: Re: matrix -> nested list
Date: 
Message-ID: <a73e72ad-9e87-4df5-8ff8-58844dbc2da7@m24g2000vbp.googlegroups.com>
On Feb 25, 9:49 am, Mirko <·············@gmail.com> wrote:
[...]
> Is there a better built-in lisp way to do the conversion, to print
> arrays?  

What you have is perfectly reasonable.

Common Lisp doesn't have all that much in the way of built-in
convenience when it comes to dealing with multidimensional arrays.
Displaced arrays and LOOP are most of what you need to build the
convenience on your own[1], as you've discovered with the code you
posted.

Cheers,
Pillsy

[1] ROW-MAJOR-AREF can also be quite helpful.
From: John Thingstad
Subject: Re: matrix -> nested list
Date: 
Message-ID: <op.upwzy1yvut4oq5@pandora.alfanett.no>
P� Wed, 25 Feb 2009 15:49:20 +0100, skrev Mirko <·············@gmail.com>:

> I am converting matrices to nested lists in order to print their
> contents using format's looping ~{, ~} directives.  For the
> convernsion, I am using the following code that I adapted from a post
> by Pascal Bourgignon
>
> (let ((arr (make-array '(3 2) :initial-contents '((1 2) (3 4) (5
> 6)))))
>   (loop
>      with element-type = (array-element-type arr)
>      with c-rows =  (array-dimension arr 1)
>      with c-cols = (array-dimension arr 0)
>      for i0 :from 0 :below c-cols
>      for row = (make-array c-rows
> 			   :displaced-to arr
> 			   :displaced-index-offset (* i0 c-rows)
> 			   :element-type element-type)
>      collect (coerce row 'list)))
>
> Is there a better built-in lisp way to do the conversion, to print
> arrays?   I guess I am reinventing the wheel (which is kind of fun),
> but I could not find the original wheel.
>
> Thank you,
>
> Mirko


CL-USER 2 : 1 > (map 'list (lambda (sub) (map 'list #'identity sub)) #(#(1  
2 3) #(4 5 6) #(7 8 9)))
((1 2 3) (4 5 6) (7 8 9))

--------------
John Thingstad
From: Pillsy
Subject: Re: matrix -> nested list
Date: 
Message-ID: <bccb3f0b-d707-44dc-9e47-0fb149e349c4@q27g2000vbn.googlegroups.com>
On Feb 25, 10:58 am, "John Thingstad" <·······@online.no> wrote:
[...]
> > Is there a better built-in lisp way to do the conversion, to print
> > arrays?   I guess I am reinventing the wheel (which is kind of fun),
> > but I could not find the original wheel.

> CL-USER 2 : 1 > (map 'list (lambda (sub) (map 'list #'identity sub))
                        #(#(1 2 3) #(4 5 6) #(7 8 9)))
> ((1 2 3) (4 5 6) (7 8 9))

The specification was for dealing with a multiple-dimensional array,
not a vector of vectors.

[1]> (map 'list (lambda (sub) (map 'list #'identity sub))
#2A((1 2 3) (4 5 6) (7 8 9)))

*** - MAP: #2A((1 2 3) (4 5 6) (7 8 9)) is not a SEQUENCE
The following restarts are available:
ABORT          :R1      Abort main loop

Cheers,
Pillsy
From: Marco Antoniotti
Subject: Re: matrix -> nested list
Date: 
Message-ID: <6706a391-55b3-4c0f-bc00-9d821555a468@t7g2000yqa.googlegroups.com>
On Feb 25, 5:06 pm, Pillsy <·········@gmail.com> wrote:
> On Feb 25, 10:58 am, "John Thingstad" <·······@online.no> wrote:
> [...]
>
> > > Is there a better built-in lisp way to do the conversion, to print
> > > arrays?   I guess I am reinventing the wheel (which is kind of fun),
> > > but I could not find the original wheel.
> > CL-USER 2 : 1 > (map 'list (lambda (sub) (map 'list #'identity sub))
>
>                         #(#(1 2 3) #(4 5 6) #(7 8 9)))
>
> > ((1 2 3) (4 5 6) (7 8 9))
>
> The specification was for dealing with a multiple-dimensional array,
> not a vector of vectors.

This is an *extremely* important observation!  It will save us from
seeing Ruby code dealing with nested vectors :)

Cheers
--
Marco
From: William James
Subject: Re: matrix -> nested list
Date: 
Message-ID: <go43cj013o8@enews5.newsguy.com>
John Thingstad wrote:

> CL-USER 2 : 1 > (map 'list (lambda (sub) (map 'list #'identity sub))
> #(#(1 2 3) #(4 5 6) #(7 8 9)))
> ((1 2 3) (4 5 6) (7 8 9))

clojure:

user=> (map #(apply list %) [[1 2 3] [4 5 6] [7 8 9]])
((1 2 3) (4 5 6) (7 8 9))
From: Raffael Cavallaro
Subject: Re: matrix -> nested list
Date: 
Message-ID: <23d4e1c3-19e6-411c-91da-9239b17dfe40@33g2000yqm.googlegroups.com>
On Feb 25, 1:41 pm, "William James" <> wrote:
>
> clojure:
>
> user=> (map #(apply list %) [[1 2 3] [4 5 6] [7 8 9]])
> ((1 2 3) (4 5 6) (7 8 9))

"First they ignore you, then they ridicule you, then they fight you,
then you win."
- Ghandi

first they ignore you and post ruby to a lisp newsgroup
then they ridicule you with "commune lisp"
then they fight you with clojure, which is a lisp
then you win
From: Marco Antoniotti
Subject: Re: matrix -> nested list
Date: 
Message-ID: <84e0aee3-56f5-4860-a500-f8a8a678c61c@r4g2000yqa.googlegroups.com>
On Feb 25, 7:50 pm, Raffael Cavallaro <················@gmail.com>
wrote:
> On Feb 25, 1:41 pm, "William James" <> wrote:
>
>
>
> > clojure:
>
> > user=> (map #(apply list %) [[1 2 3] [4 5 6] [7 8 9]])
> > ((1 2 3) (4 5 6) (7 8 9))
>
> "First they ignore you, then they ridicule you, then they fight you,
> then you win."
> - Ghandi
>
> first they ignore you and post ruby to a lisp newsgroup
> then they ridicule you with "commune lisp"
> then they fight you with clojure, which is a lisp
> then you win

Nahhh!  I don't want to win... We won't have any more fun then.
BTW.  I did not know that Clojure had N-dimensional arrays. :)

Cheers
--
Marco
From: Pascal J. Bourguignon
Subject: Re: matrix -> nested list
Date: 
Message-ID: <7ck57ewkjf.fsf@pbourguignon.anevia.com>
Mirko <·············@gmail.com> writes:

> I am converting matrices to nested lists in order to print their
> contents using format's looping ~{, ~} directives.  

This is not a good idea.  It would be better to write a formatter
function for you matrices.

   (format t "My matrix is: ~/matrix-formatter/ ~%" matrix)



-- 
__Pascal Bourguignon__
From: Mirko
Subject: Re: matrix -> nested list
Date: 
Message-ID: <b706ed15-bc52-4316-ac21-e69306211ae0@h5g2000yqh.googlegroups.com>
On Feb 25, 11:25 am, ····@informatimago.com (Pascal J. Bourguignon)
wrote:
> Mirko <·············@gmail.com> writes:
> > I am converting matrices to nested lists in order to print their
> > contents using format's looping ~{, ~} directives.  
>
> This is not a good idea.  It would be better to write a formatter
> function for you matrices.
>
>    (format t "My matrix is: ~/matrix-formatter/ ~%" matrix)
>
> --
> __Pascal Bourguignon__

Hm, let me try that.
From: Mirko
Subject: matrix formatting (was:  matrix -> nested list)
Date: 
Message-ID: <54c6ec23-e09f-4b4f-8759-869fddffa6f2@41g2000yqf.googlegroups.com>
On Feb 25, 1:02 pm, Mirko <·············@gmail.com> wrote:
> On Feb 25, 11:25 am, ····@informatimago.com (Pascal J. Bourguignon)
> wrote:
>
> > Mirko <·············@gmail.com> writes:
> > > I am converting matrices to nested lists in order to print their
> > > contents using format's looping ~{, ~} directives.  
>
> > This is not a good idea.  It would be better to write a formatter
> > function for you matrices.
>
> >    (format t "My matrix is: ~/matrix-formatter/ ~%" matrix)
>
> > --
> > __Pascal Bourguignon__
>
> Hm, let me try that.

I got this far:

(defun format-matrix (stream matrix colon-t at-sign-t &rest rest)
  (format stream "~{~{~a ~}~^~%~}" (matrix->nested-list matrix)))

and this works:
CL-USER>
(let ((arr (make-array '(3 2) :initial-contents '((1 2) (3.14 4) (5
6)))))
  (format t "~/matrix-format/~%" arr))
1 2
3.14 4
5 6
NIL

But, I would like to pass a formatting argument to matrix-format (like
on of lisp's standard constructs : f, g, etc):
(format t "~5f/matrix-format/" matrix)

But the ~5f executes first.  Is there some way around that?

Thanks,

Mirko
From: John Thingstad
Subject: Re: matrix formatting (was:  matrix -> nested list)
Date: 
Message-ID: <op.upw98lm1ut4oq5@pandora.alfanett.no>
P� Wed, 25 Feb 2009 20:16:30 +0100, skrev Mirko <·············@gmail.com>:

> On Feb 25, 1:02�pm, Mirko <·············@gmail.com> wrote:
>> On Feb 25, 11:25�am, ····@informatimago.com (Pascal J. Bourguignon)
>> wrote:
>>
>> > Mirko <·············@gmail.com> writes:
>> > > I am converting matrices to nested lists in order to print their
>> > > contents using format's looping ~{, ~} directives. �
>>
>> > This is not a good idea. �It would be better to write a formatter
>> > function for you matrices.
>>
>> > � �(format t "My matrix is: ~/matrix-formatter/ ~%" matrix)
>>
>> > --
>> > __Pascal Bourguignon__
>>
>> Hm, let me try that.
>
> I got this far:
>
> (defun format-matrix (stream matrix colon-t at-sign-t &rest rest)
>   (format stream "~{~{~a ~}~^~%~}" (matrix->nested-list matrix)))
>
> and this works:
> CL-USER>
> (let ((arr (make-array '(3 2) :initial-contents '((1 2) (3.14 4) (5
> 6)))))
>   (format t "~/matrix-format/~%" arr))
> 1 2
> 3.14 4
> 5 6
> NIL
>
> But, I would like to pass a formatting argument to matrix-format (like
> on of lisp's standard constructs : f, g, etc):
> (format t "~5f/matrix-format/" matrix)
>
> But the ~5f executes first.  Is there some way around that?
>
> Thanks,
>
> Mirko

You are still misssing the point that your code for printing matrixes is  
inefficient. Just iterate over the array and print the values insted.

 From hyperspec:

22.3.5.4 Tilde Slash: Call Function
~/name/

User defined functions can be called from within a format string by using  
the directive ~/name/. The colon modifier, the at-sign modifier, and  
arbitrarily many parameters can be specified with the ~/name/ directive.  
name can be any arbitrary string that does not contain a "/". All of the  
characters in name are treated as if they were upper case. If name  
contains a single colon (:) or double colon (::), then everything up to  
but not including the first ":" or "::" is taken to be a string that names  
a package. Everything after the first ":" or "::" (if any) is taken to be  
a string that names a symbol. The function corresponding to a ~/name/  
directive is obtained by looking up the symbol that has the indicated name  
in the indicated package. If name does not contain a ":" or "::", then the  
whole name string is looked up in the COMMON-LISP-USER package.

When a ~/name/ directive is encountered, the indicated function is called  
with four or more arguments. The first four arguments are: the output  
stream, the format argument corresponding to the directive, a generalized  
boolean that is true if the colon modifier was used, and a generalized  
boolean that is true if the at-sign modifier was used. The remaining  
arguments consist of any parameters specified with the directive. The  
function should print the argument appropriately. Any values returned by  
the function are ignored.


--------------
John Thingstad
From: Pascal J. Bourguignon
Subject: Re: matrix formatting
Date: 
Message-ID: <877i3e8bbk.fsf@galatea.local>
"John Thingstad" <·······@online.no> writes:

> P� Wed, 25 Feb 2009 20:16:30 +0100, skrev Mirko <·············@gmail.com>:
>
>> On Feb 25, 1:02�pm, Mirko <·············@gmail.com> wrote:
>>> On Feb 25, 11:25�am, ····@informatimago.com (Pascal J. Bourguignon)
>>> wrote:
>>>
>>> > Mirko <·············@gmail.com> writes:
>>> > > I am converting matrices to nested lists in order to print their
>>> > > contents using format's looping ~{, ~} directives. �
>>>
>>> > This is not a good idea. �It would be better to write a formatter
>>> > function for you matrices.
>>>
>>> > � �(format t "My matrix is: ~/matrix-formatter/ ~%" matrix)
>>>
>>> > --
>>> > __Pascal Bourguignon__
>>>
>>> Hm, let me try that.
>>
>> I got this far:
>>
>> (defun format-matrix (stream matrix colon-t at-sign-t &rest rest)
>>   (format stream "~{~{~a ~}~^~%~}" (matrix->nested-list matrix)))
>>
>> and this works:
>> CL-USER>
>> (let ((arr (make-array '(3 2) :initial-contents '((1 2) (3.14 4) (5
>> 6)))))
>>   (format t "~/matrix-format/~%" arr))
>> 1 2
>> 3.14 4
>> 5 6
>> NIL
>>
>> But, I would like to pass a formatting argument to matrix-format (like
>> on of lisp's standard constructs : f, g, etc):
>> (format t "~5f/matrix-format/" matrix)
>>
>> But the ~5f executes first.  Is there some way around that?

You can use the rest arguments.  For example, we could take forward
the arguments, only for the last character being the specifier, and if
there are colon and at characters just before, as the modifiers:


(defun matrix-format (stream matrix colon-t at-sign-t &rest rest)
  (let* ((tser (reverse rest))
         (spec (pop tser))
         (flg1 (when (position (first tser) ··@") (pop tser)))
         (flg2 (when (position (first tser) ··@") (pop tser)))
         (args (mapcar (lambda (arg) (cond ((null arg)"")
                                      ((integerp arg) arg)
                                      (t `',arg)))
                       (reverse tser)))
         (ctrl (format nil "~~~{~:[~;~:*~A~]~^,~}~:[~;~:*~A~]~:[~;~:*~A~]~A " 
                       args flg1 flg2 spec)))
    (loop
       :for i :from 0 :below (array-dimension matrix 0)
       :do (loop
              :for j :from 0 :below (array-dimension matrix 1)
              :do (format stream ctrl (aref matrix i j))
              :finally (format stream "~%")))))



C/USER[867]> (format t "~5,,,,'#,'F/matrix-format/" #2A((1 2 3) (4 5 6)))
##1.0 ##2.0 ##3.0 
##4.0 ##5.0 ##6.0 
NIL
C/USER[868]> (format t "~5,·@,'A/matrix-format/" #2A((1 2 3) (4 5 6)))
    1     2     3 
    4     5     6 
NIL
C/USER[869]> (format t "~5,'A/matrix-format/" #2A((1 2 3) (4 5 6)))
1     2     3     
4     5     6     
NIL
C/USER[870]> 


> You are still misssing the point that your code for printing matrixes
> is  inefficient. Just iterate over the array and print the values
> insted.

Yes, but it doesn't matter, once the correct architecture is in place,
we can change matrix-format later to optimize it for big matrices.

-- 
__Pascal Bourguignon__
From: Mirko
Subject: Re: matrix formatting
Date: 
Message-ID: <123e9bd5-07a3-44fd-bd35-92c84bef3f05@e5g2000vbe.googlegroups.com>
On Feb 25, 4:18 pm, ····@informatimago.com (Pascal J. Bourguignon)
wrote:
> "John Thingstad" <·······@online.no> writes:
> > På Wed, 25 Feb 2009 20:16:30 +0100, skrev Mirko <·············@gmail.com>:
>
> >> On Feb 25, 1:02 pm, Mirko <·············@gmail.com> wrote:
> >>> On Feb 25, 11:25 am, ····@informatimago.com (Pascal J. Bourguignon)
> >>> wrote:
>
> >>> > Mirko <·············@gmail.com> writes:
> >>> > > I am converting matrices to nested lists in order to print their
> >>> > > contents using format's looping ~{, ~} directives.  
>
> >>> > This is not a good idea.  It would be better to write a formatter
> >>> > function for you matrices.
>
> >>> >    (format t "My matrix is: ~/matrix-formatter/ ~%" matrix)
>
> >>> > --
> >>> > __Pascal Bourguignon__
>
> >>> Hm, let me try that.
>
> >> I got this far:
>
> >> (defun format-matrix (stream matrix colon-t at-sign-t &rest rest)
> >>   (format stream "~{~{~a ~}~^~%~}" (matrix->nested-list matrix)))
>
> >> and this works:
> >> CL-USER>
> >> (let ((arr (make-array '(3 2) :initial-contents '((1 2) (3.14 4) (5
> >> 6)))))
> >>   (format t "~/matrix-format/~%" arr))
> >> 1 2
> >> 3.14 4
> >> 5 6
> >> NIL
>
> >> But, I would like to pass a formatting argument to matrix-format (like
> >> on of lisp's standard constructs : f, g, etc):
> >> (format t "~5f/matrix-format/" matrix)
>
> >> But the ~5f executes first.  Is there some way around that?
>
> You can use the rest arguments.  For example, we could take forward
> the arguments, only for the last character being the specifier, and if
> there are colon and at characters just before, as the modifiers:
>
> (defun matrix-format (stream matrix colon-t at-sign-t &rest rest)
>   (let* ((tser (reverse rest))
>          (spec (pop tser))
>          (flg1 (when (position (first tser) ··@") (pop tser)))
>          (flg2 (when (position (first tser) ··@") (pop tser)))
>          (args (mapcar (lambda (arg) (cond ((null arg)"")
>                                       ((integerp arg) arg)
>                                       (t `',arg)))
>                        (reverse tser)))
>          (ctrl (format nil "~~~{~:[~;~:*~A~]~^,~}~:[~;~:*~A~]~:[~;~:*~A~]~A "
>                        args flg1 flg2 spec)))
>     (loop
>        :for i :from 0 :below (array-dimension matrix 0)
>        :do (loop
>               :for j :from 0 :below (array-dimension matrix 1)
>               :do (format stream ctrl (aref matrix i j))
>               :finally (format stream "~%")))))
>
> C/USER[867]> (format t "~5,,,,'#,'F/matrix-format/" #2A((1 2 3) (4 5 6)))
> ##1.0 ##2.0 ##3.0
> ##4.0 ##5.0 ##6.0
> NIL
> C/USER[868]> (format t "~5,·@,'A/matrix-format/" #2A((1 2 3) (4 5 6)))
>     1     2     3
>     4     5     6
> NIL
> C/USER[869]> (format t "~5,'A/matrix-format/" #2A((1 2 3) (4 5 6)))
> 1     2     3    
> 4     5     6    
> NIL
> C/USER[870]>
>
> > You are still misssing the point that your code for printing matrixes
> > is  inefficient. Just iterate over the array and print the values
> > insted.
>
> Yes, but it doesn't matter, once the correct architecture is in place,
> we can change matrix-format later to optimize it for big matrices.
>
> --
> __Pascal Bourguignon__

Couple of points:

1) thanks
2) I think John's statement about efficiency did finally sink in
3) I knew about the `rest', but not about quoting the args to the
formatting function
4) It will take me a few hours to parse the totem-pole format
string :-)

Thanks again,

Mirko
From: Pascal J. Bourguignon
Subject: Re: matrix formatting
Date: 
Message-ID: <7c8wntwlzz.fsf@pbourguignon.anevia.com>
Mirko <·············@gmail.com> writes:
> 4) It will take me a few hours to parse the totem-pole format
> string :-)

It's easy actually: there are parentheses! (but they're strange it's
true, {} and []):

 "~~~{~:[~;~:*~A~]~^,~}~:[~;~:*~A~]~:[~;~:*~A~]~A "      
  ~~                                                     prints ~
    ~{~:[~;~:*~A~]~^,~}                                  loop
      ~:[~;~:*~A~]                                          prints the argument unless it's NIL
                    ,                                       prints , if not done
                       ~:[~;~:*~A~]                      prints the argument unless it's NIL
                                   ~:[~;~:*~A~]          prints the argument unless it's NIL
                                               ~A        prints the argument
                                       a space ->        prints a space


~:[~;~:*~A~] is a IF/THEN :  ~:[ =  if argument is nil then
                             ~;  =  else
                             ~]  =  end

~:* seeks back one position in the argument list.  So we print with ~A
the same argument as used in the if.  There may be an invocation of ~[
to do the same in less characters, but I don't remember and I'm lazy
searching it again.


-- 
__Pascal Bourguignon__
From: Marco Antoniotti
Subject: Re: matrix formatting
Date: 
Message-ID: <30a9bde0-5362-46d3-8b05-01b597c73d93@x13g2000yqf.googlegroups.com>
On Feb 26, 11:06 am, ····@informatimago.com (Pascal J. Bourguignon)
wrote:
> Mirko <·············@gmail.com> writes:
> > 4) It will take me a few hours to parse the totem-pole format
> > string :-)
>
> It's easy actually: there are parentheses! (but they're strange it's
> true, {} and []):
>
>  "~~~{~:[~;~:*~A~]~^,~}~:[~;~:*~A~]~:[~;~:*~A~]~A "      
>   ~~                                                     prints ~
>     ~{~:[~;~:*~A~]~^,~}                                  loop
>       ~:[~;~:*~A~]                                          prints the argument unless it's NIL
>                     ,                                       prints , if not done
>                        ~:[~;~:*~A~]                      prints the argument unless it's NIL
>                                    ~:[~;~:*~A~]          prints the argument unless it's NIL
>                                                ~A        prints the argument
>                                        a space ->        prints a space
>
> ~:[~;~:*~A~] is a IF/THEN :  ~:[ =  if argument is nil then
>                              ~;  =  else
>                              ~]  =  end
>
> ~:* seeks back one position in the argument list.  So we print with ~A
> the same argument as used in the if.  There may be an invocation of ~[
> to do the same in less characters, but I don't remember and I'm lazy
> searching it again.

I think you are thinking of ·@[
I always have to look it up.

Cheers
--
Marco
ELS 2009 www.european-lisp-symposium.org
From: Pascal J. Bourguignon
Subject: Re: matrix formatting
Date: 
Message-ID: <7cskm1usgt.fsf@pbourguignon.anevia.com>
Marco Antoniotti <·······@gmail.com> writes:

> On Feb 26, 11:06�am, ····@informatimago.com (Pascal J. Bourguignon)
> wrote:
>> Mirko <·············@gmail.com> writes:
>> > 4) It will take me a few hours to parse the totem-pole format
>> > string :-)
>>
>> It's easy actually: there are parentheses! (but they're strange it's
>> true, {} and []):
>>
>> �"~~~{~:[~;~:*~A~]~^,~}~:[~;~:*~A~]~:[~;~:*~A~]~A " � � �
>> � ~~ � � � � � � � � � � � � � � � � � � � � � � � � � � prints ~
>> � � ~{~:[~;~:*~A~]~^,~} � � � � � � � � � � � � � � � � �loop
>> � � � ~:[~;~:*~A~] � � � � � � � � � � � � � � � � � � � � �prints the argument unless it's NIL
>> � � � � � � � � � � , � � � � � � � � � � � � � � � � � � � prints , if not done
>> � � � � � � � � � � � �~:[~;~:*~A~] � � � � � � � � � � �prints the argument unless it's NIL
>> � � � � � � � � � � � � � � � � � �~:[~;~:*~A~] � � � � �prints the argument unless it's NIL
>> � � � � � � � � � � � � � � � � � � � � � � � �~A � � � �prints the argument
>> � � � � � � � � � � � � � � � � � � � �a space -> � � � �prints a space
>>
>> ~:[~;~:*~A~] is a IF/THEN : �~:[ = �if argument is nil then
>> � � � � � � � � � � � � � � �~; �= �else
>> � � � � � � � � � � � � � � �~] �= �end
>>
>> ~:* seeks back one position in the argument list. �So we print with ~A
>> the same argument as used in the if. �There may be an invocation of ~[
>> to do the same in less characters, but I don't remember and I'm lazy
>> searching it again.
>
> I think you are thinking of ·@[
> I always have to look it up.

Indeed. Thanks.

So we can simplify the control string to: ······@[~A~]~^,···@[~A~]·@[~A~]~A "


-- 
__Pascal Bourguignon__
From: Mirko
Subject: Re: matrix formatting
Date: 
Message-ID: <706f4861-acdc-4a1c-87ec-491dbd5472ff@w9g2000yqa.googlegroups.com>
On Feb 26, 5:06 am, ····@informatimago.com (Pascal J. Bourguignon)
wrote:
> Mirko <·············@gmail.com> writes:
> > 4) It will take me a few hours to parse the totem-poleformat
> > string :-)
>
> It's easy actually: there are parentheses! (but they're strange it's
> true, {} and []):
>
>  "~~~{~:[~;~:*~A~]~^,~}~:[~;~:*~A~]~:[~;~:*~A~]~A "      
>   ~~                                                     prints ~
>     ~{~:[~;~:*~A~]~^,~}                                  loop
>       ~:[~;~:*~A~]                                          prints the argument unless it's NIL
>                     ,                                       prints , if not done
>                        ~:[~;~:*~A~]                      prints the argument unless it's NIL
>                                    ~:[~;~:*~A~]          prints the argument unless it's NIL
>                                                ~A        prints the argument
>                                        a space ->        prints a space
>
> ~:[~;~:*~A~] is a IF/THEN :  ~:[ =  if argument is nil then
>                              ~;  =  else
>                              ~]  =  end
>
> ~:* seeks back one position in the argument list.  So we print with ~A
> the same argument as used in the if.  There may be an invocation of ~[
> to do the same in less characters, but I don't remember and I'm lazy
> searching it again.
>
> --
> __Pascal Bourguignon__

Ding!  Got it (and the ·@[ version as well).  Thanks.