From: Mark Carter
Subject: Thrown for a loop
Date: 
Message-ID: <43ff9e86$0$15792$14726298@news.sunsite.dk>
Suppose I want to create a nested looping structure that returned the list
((1 1) (1 2) (1 3) 1 (2 1) (2 2) (2 3) 2)

I tried doing

(loop for r from 1 to 2
	collect (loop for c from 1 to 3 collect (list r c))
	collect r)

but I end up with

(((1 1) (1 2) (1 3)) 1 ((2 1) (2 2) (2 3)) 2)

I also tried a loop like

(loop for r from 1 to 2
   for c from 1 to 3
   ...)

but that didn't work either. What is it that I need to do? It all seems 
a bit of a dark art.

From: Tayssir John Gabbour
Subject: Re: Thrown for a loop
Date: 
Message-ID: <1140827653.379495.326070@i39g2000cwa.googlegroups.com>
Mark Carter wrote:
> Suppose I want to create a nested looping structure that returned the list
> ((1 1) (1 2) (1 3) 1 (2 1) (2 2) (2 3) 2)
>
> I tried doing
>
> (loop for r from 1 to 2
> 	collect (loop for c from 1 to 3 collect (list r c))
> 	collect r)

Hi,

Very close. Try append rather than the first collect.

Tayssir
From: ········@gmail.com
Subject: Re: Thrown for a loop
Date: 
Message-ID: <1140855410.329293.292850@i39g2000cwa.googlegroups.com>
I like iterate as an alternative:

        (iter outer
               (for r from 1 to 2)
               (iter (for c from 1 to 3)
                     (in outer (collect (list r c))))
               (collect r))
From: Kenny Tilton
Subject: Re: Thrown for a loop
Date: 
Message-ID: <9oVLf.6433$cF5.3785@news-wrt-01.rdc-nyc.rr.com>
········@gmail.com wrote:
> I like iterate as an alternative:
> 
>         (iter outer
>                (for r from 1 to 2)
>                (iter (for c from 1 to 3)
>                      (in outer (collect (list r c))))
>                (collect r))
> 

That is pretty damn cool.

But thinking like a teacher, I am concerned that the OP thought they 
could (effectively):

    (list '(a b) c) -> (a b c) ;; crazy!!!

Ok, what they actually wanted was:

    (list '((1 2)(3 4)) 5) -> ((1 2)(3 4) 5) ;; crazy!!!

..but that is the same thing.

Didactically speaking, methinks one wants more to get folks to 
understand that Lisp does not and should not and really cannot guess 
what we want. Fact is:

   (list x y) -> (x y)

Therefore (list '(1 2) 3) -> ((1 2) 3). Any lisp behaving:

   (list '(1 2) 3) -> (1 2 3)

...is so broken as to be unprogrammable. The Op wants that behavior, but 
someday they will (list (1 2) 3) and want ((1 2) 3). They are dead, 
their Lisp will give them what it thinks they want, (1 2 3).

    (iterate ... (in <xx> (collect...)))

Is a nice way to do nconc, but the OP should undersatnd that vital 
difference between nconc and list.

I am not sure that "(in xxx (collect .....))" conveys that.

ken
From: Tayssir John Gabbour
Subject: Re: Thrown for a loop
Date: 
Message-ID: <1140868528.459278.267140@v46g2000cwv.googlegroups.com>
Kenny Tilton wrote:
> But thinking like a teacher, I am concerned that the OP thought they
> could (effectively):
>
>     (list '(a b) c) -> (a b c) ;; crazy!!!
>
> Ok, what they actually wanted was:
>
>     (list '((1 2)(3 4)) 5) -> ((1 2)(3 4) 5) ;; crazy!!!
>
> ..but that is the same thing.
>
> Didactically speaking, methinks one wants more to get folks to
> understand that Lisp does not and should not and really cannot guess
> what we want.


I have to admit, it took me a while to grok the difference between
append/collect and mapcan/mapcar, particularly in recursive processes.
Essentially, the way I learned it was to gain the intuition first from
trial & error, then more intellectually later.

(I think John Dewey may have said something interesting about this sort
of education.)

Maybe using TRACE for mapcan/mapcar and printing named accumulation
variables (with loop) might help. I was impressed yesterday by the
metaobject protocol tutorials by Manuel Odendahl because it seemed to
be the only tutorial-type thing for the mop using DESCRIBE and TRACE.
http://wiki.alu.org/Metaobject_Protocol

Perhaps loop needs a trace facility.


Tayssir
From: Mark Carter
Subject: Re: Thrown for a loop
Date: 
Message-ID: <44003579$0$15781$14726298@news.sunsite.dk>
Kenny Tilton wrote:

> But thinking like a teacher, I am concerned that the OP thought they 
> could (effectively):

What I was actually doing is that I had a matrix, represented as a flat 
list. The operation I was attempting to perform was to add a column to 
the end of the matrix. Here's the code I eventually came up with:
(defun add-col ()
   (when (< *cols* *max-cols*)
     (let ((new-grid
	   (loop for r from 1 to *rows*
		 append (loop for c from 1 to *cols*
			      collect (rc r c))
		 collect #\Space)))	
	  (setq *grid* new-grid))
     (inc! *cols*)))

Thanks go to the poster who recommended changing collect to append. I 
had simplified the problem when I presented it to this newsgroup. One of 
the problems as a noob to lisp is that there is a smorgasbord of things 
to choose from, and it can be difficult to discern which thing one 
wants, and exactly how it is supposed to operate.

The "append" statement gets the original row, whilst the "collect" 
statement tacks on an additional character (it's a matrix of characters 
rather than numbers).

So, "job's a good'un", as they say up North.
From: Kenny Tilton
Subject: Re: Thrown for a loop
Date: 
Message-ID: <4_0Mf.5601$uV6.3721@news-wrt-01.rdc-nyc.rr.com>
Mark Carter wrote:
> Kenny Tilton wrote:
> 
>> But thinking like a teacher, I am concerned that the OP thought they 
>> could (effectively):
> 
> 
> What I was actually doing is that I had a matrix, represented as a flat 
> list.

That is a pretty scary sentence. Why not represent a matrix as a matrix?

> The operation I was attempting to perform was to add a column to 
> the end of the matrix. Here's the code I eventually came up with:
> (defun add-col ()
>   (when (< *cols* *max-cols*)
>     (let ((new-grid
>        (loop for r from 1 to *rows*
>          append (loop for c from 1 to *cols*
>                   collect (rc r c))
>          collect #\Space)))   
>       (setq *grid* new-grid))
>     (inc! *cols*)))
> 
> Thanks go to the poster who recommended changing collect to append.

What was wrong with my suggestion of NCONC? :)

My feelings are not hurt,  this is a hint about a big Lisp learning 
issue: one needs to know when one can use destructive operations. It may 
not matter in this case, but as one of our old sayings goes, "It does 
not cost any more to do it right."

> I 
> had simplified the problem when I presented it to this newsgroup. One of 
> the problems as a noob to lisp is that there is a smorgasbord of things 
> to choose from, and it can be difficult to discern which thing one 
> wants, and exactly how it is supposed to operate.

Yep. Ten years now heads-down use and I am still learning.

> 
> The "append" statement gets the original row, whilst the "collect" 
> statement tacks on an additional character (it's a matrix of characters 
> rather than numbers).
> 
> So, "job's a good'un", as they say up North.

Not so sure. I am /really/ worried about you tossing a dimension of your 
conceptual data structure in representing it.

kenny
From: Mark Carter
Subject: Re: Thrown for a loop
Date: 
Message-ID: <4400ad2b$0$15791$14726298@news.sunsite.dk>
Kenny Tilton wrote:

> Not so sure. I am /really/ worried about you tossing a dimension of your 
> conceptual data structure in representing it.

Hmm, I suppose a list of "cells" would be an interesting choice.

I am even toying with the idea of ditching the flexibility to add rows 
and columns. I can then eliminate code, making the program shorter.
From: Kenny Tilton
Subject: Re: Thrown for a loop
Date: 
Message-ID: <vINLf.5581$uV6.4425@news-wrt-01.rdc-nyc.rr.com>
Mark Carter wrote:
> Suppose I want to create a nested looping structure that returned the list
> ((1 1) (1 2) (1 3) 1 (2 1) (2 2) (2 3) 2)
> 
> I tried doing
> 
> (loop for r from 1 to 2
>     collect (loop for c from 1 to 3 collect (list r c))
>     collect r)
> 
> but I end up with
> 
> (((1 1) (1 2) (1 3)) 1 ((2 1) (2 2) (2 3)) 2)
> 
> I also tried a loop like
> 
> (loop for r from 1 to 2
>   for c from 1 to 3
>   ...)
> 
> but that didn't work either. What is it that I need to do?

(loop for r from 1 to 2
     nconc (loop for c from 1 to 3 collect (list r c))
     collect r)

> It all seems 
> a bit of a dark art.

No it doesn't. :) You just have to slow down and notice that in your 
first try you were collecting /lists/ of pairs, so naturally the result 
included the collected pairs each set in their own list.

Your desired result is a bit odd. You want the lists of pairs spliced 
into the result, ie, you want the toplevel list in which you are 
generating the pairs (your inner loop/collect) to go away.

We use things like nconc and mapcan for that.

kenny