From: Mozis
Subject: Problem while adding -1 in loop
Date: 
Message-ID: <1159760849.259254.198460@e3g2000cwe.googlegroups.com>
Greetings,

I am newbie to the Lisp and quite a bit in learning phase.
I had done the following decrement steps,

(loop for i from 5 to 1 by -1
    do
    (print i)
)

Answer:
nil

expected ans
5
4
3
2
1
nil

Now I changed the code a little bit as follows,

I am newbie to the Lisp and quite a bit in learning phase.

(loop for i from 5 downto 1 by 1
    do
    (print i)
)


I am not getting why it's not just adding -1 to the value.

Could anybody help me out.

Thanks,

Mozis.

From: Bill Atkins
Subject: Re: Problem while adding -1 in loop
Date: 
Message-ID: <m2mz8fwdzr.fsf@bertrand.local>
"Mozis" <···············@gmail.com> writes:

> Greetings,
>
> I am newbie to the Lisp and quite a bit in learning phase.
> I had done the following decrement steps,
>
> (loop for i from 5 to 1 by -1
>     do
>     (print i)
> )
>
> Answer:
> nil
>
> expected ans
> 5
> 4
> 3
> 2
> 1
> nil
>
> Now I changed the code a little bit as follows,
>
> I am newbie to the Lisp and quite a bit in learning phase.
>
> (loop for i from 5 downto 1 by 1
>     do
>     (print i)
> )
>
>
> I am not getting why it's not just adding -1 to the value.
>
> Could anybody help me out.
>
> Thanks,
>
> Mozis.

The short answer is that LOOP needs to be told whether it should count
down or up.  So you would need to say (loop for i from 5 downto 1 do
(print i)).  The first version won't work because LOOP assumes that TO
means "count upward."

The reason for this is that LOOP is a macro.  At compile time, it
accepts the actual code inside the LOOP form.  Although in your
example it seems clear that "from 5 to 1 by -1" should step downward,
this is not the case in general.  For example, you could have the
following LOOP form: (loop for x from a to b by c ...).  This is a
perfectly valid LOOP.  The problem is that at compile time, LOOP only
knows that you are using the variables A, B, and C, but has no way of
knowing what those variables might contain at runtime.

Thus:

(let ((a 3) (b 1) (c -1))
  (loop for i from a to b by c collect i))

won't work, because LOOP assumes you want to count upward.  You need
to specify that you want LOOP to step downward with a DOWNTO clause.

HTH,
Bill
From: Frank Buss
Subject: Re: Problem while adding -1 in loop
Date: 
Message-ID: <vz24jyd2nlez$.1rk58j3a142nl.dlg@40tude.net>
Bill Atkins wrote:

> The short answer is that LOOP needs to be told whether it should count
> down or up.  So you would need to say (loop for i from 5 downto 1 do
> (print i)).  The first version won't work because LOOP assumes that TO
> means "count upward."
> 
> The reason for this is that LOOP is a macro.

I don't see why this is a reason for loop to fail:

(defmacro my-loop (from to)
  `(if (> ,to ,from)
       (loop for i from ,from to ,to collect i)
     (loop for i from ,from downto ,to collect i)))

CL-USER > (my-loop 0 10)
(10 9 8 7 6 5 4 3 2 1 0)

CL-USER > (let ((a 3) (b 1)) (my-loop a b))
(3 2 1)

-- 
Frank Buss, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
From: Bill Atkins
Subject: Re: Problem while adding -1 in loop
Date: 
Message-ID: <m2irj3mheu.fsf@bertrand.local>
Frank Buss <··@frank-buss.de> writes:

> Bill Atkins wrote:
>
>> The short answer is that LOOP needs to be told whether it should count
>> down or up.  So you would need to say (loop for i from 5 downto 1 do
>> (print i)).  The first version won't work because LOOP assumes that TO
>> means "count upward."
>> 
>> The reason for this is that LOOP is a macro.
>
> I don't see why this is a reason for loop to fail:
>
> (defmacro my-loop (from to)
>   `(if (> ,to ,from)
>        (loop for i from ,from to ,to collect i)
>      (loop for i from ,from downto ,to collect i)))
>
> CL-USER > (my-loop 0 10)
> (10 9 8 7 6 5 4 3 2 1 0)
>
> CL-USER > (let ((a 3) (b 1)) (my-loop a b))
> (3 2 1)

It could be done, but MY-LOOP's expansion is twice as big as it has to
be.  You could write a new LOOP that does this comparison at runtime
to figure out how it should do the stepping, but this would be
somewhat wasteful just to take care of a special case.
From: Ken Tilton
Subject: Re: Problem while adding -1 in loop
Date: 
Message-ID: <Nn3Ug.53$XM.0@newsfe08.lga>
Frank Buss wrote:
> Bill Atkins wrote:
> 
> 
>>The short answer is that LOOP needs to be told whether it should count
>>down or up.  So you would need to say (loop for i from 5 downto 1 do
>>(print i)).  The first version won't work because LOOP assumes that TO
>>means "count upward."
>>
>>The reason for this is that LOOP is a macro.
> 
> 
> I don't see why this is a reason for loop to fail:
> 
> (defmacro my-loop (from to)
>   `(if (> ,to ,from)
>        (loop for i from ,from to ,to collect i)
>      (loop for i from ,from downto ,to collect i)))

The reason is that we cannot have a DWIM language. By which I mean "a 
language that guesses at what I am doing", however good its intentions. 
I do enough damage with languages that do exactly what I tell them, ya 
really wanna see how much damage I can do with a language that tries to 
read my mind?

What if I write some code that computes a start and computes a finish 
and banks on the language (or macro) having half a brain and knowing 
that going from one to zero is very short path having no iterations? (I 
actually do this all the time.) But your code figures out what I really 
meant (no!!!!!!!!!!!!!!!!!!) and come hell or high water finds a way to 
iterate over values I never meant to touch.

Fabulous. This is how we lose satellites to Mars, land AirBusses in 
forests, and destroy Moscow inadvertently.

hth, kenny

-- 
Cells: http://common-lisp.net/project/cells/

"I'll say I'm losing my grip, and it feels terrific."
    -- Smiling husband to scowling wife, New Yorker cartoon
From: Ken Tilton
Subject: Re: Problem while adding -1 in loop
Date: 
Message-ID: <AQ3Ug.98$WG3.82@newsfe09.lga>
Ken Tilton wrote:
> 
> 
> Frank Buss wrote:
> 
>> Bill Atkins wrote:
>>
>>
>>> The short answer is that LOOP needs to be told whether it should count
>>> down or up.  So you would need to say (loop for i from 5 downto 1 do
>>> (print i)).  The first version won't work because LOOP assumes that TO
>>> means "count upward."
>>>
>>> The reason for this is that LOOP is a macro.
>>
>>
>>
>> I don't see why this is a reason for loop to fail:
>>
>> (defmacro my-loop (from to)
>>   `(if (> ,to ,from)
>>        (loop for i from ,from to ,to collect i)
>>      (loop for i from ,from downto ,to collect i)))
> 
> 
> The reason is that we cannot have a DWIM language.

Uh, sorry: I see what you were actually targeting was "the reason is 
that loop is a macro". Right, macro or not is not the issue.

kt

-- 
Cells: http://common-lisp.net/project/cells/

"I'll say I'm losing my grip, and it feels terrific."
    -- Smiling husband to scowling wife, New Yorker cartoon
From: Bill Atkins
Subject: Re: Problem while adding -1 in loop
Date: 
Message-ID: <m264f27mls.fsf@bertrand.local>
Ken Tilton <·········@gmail.com> writes:

> Ken Tilton wrote:
>>
>>
>> Frank Buss wrote:
>>
>>> Bill Atkins wrote:
>>>
>>>
>>>> The short answer is that LOOP needs to be told whether it should count
>>>> down or up.  So you would need to say (loop for i from 5 downto 1 do
>>>> (print i)).  The first version won't work because LOOP assumes that TO
>>>> means "count upward."
>>>>
>>>> The reason for this is that LOOP is a macro.
>>>
>>>
>>>
>>> I don't see why this is a reason for loop to fail:
>>>
>>> (defmacro my-loop (from to)
>>>   `(if (> ,to ,from)
>>>        (loop for i from ,from to ,to collect i)
>>>      (loop for i from ,from downto ,to collect i)))
>>
>>
>> The reason is that we cannot have a DWIM language.
>
> Uh, sorry: I see what you were actually targeting was "the reason is
> that loop is a macro". Right, macro or not is not the issue.

Yikes.  You're right (in my defense, I made these posts late at night
after a long day :). The actual reason is that "LOOP, which happens to
be a macro, is specified to work that way."
From: Ralf Mattes
Subject: Re: Problem while adding -1 in loop
Date: 
Message-ID: <pan.2006.10.02.13.06.20.765794@mh-freiburg.de>
On Mon, 02 Oct 2006 00:14:32 -0400, Bill Atkins wrote:

> "Mozis" <···············@gmail.com> writes:
> 
>> Greetings,
>>
>> I am newbie to the Lisp and quite a bit in learning phase.
>> I had done the following decrement steps,
>>
>> (loop for i from 5 to 1 by -1
>>     do
>>     (print i)
>> )
>>
>> Answer:
>> nil
>>
>> expected ans
>> 5
>> 4
>> 3
>> 2
>> 1
>> nil
>>
>> Now I changed the code a little bit as follows,
>>
>> I am newbie to the Lisp and quite a bit in learning phase.
>>
>> (loop for i from 5 downto 1 by 1
>>     do
>>     (print i)
>> )
>>
>>
>> I am not getting why it's not just adding -1 to the value.
>>
>> Could anybody help me out.
>>
>> Thanks,
>>
>> Mozis.
> 
> The short answer is that LOOP needs to be told whether it should count
> down or up.  So you would need to say (loop for i from 5 downto 1 do
> (print i)).  The first version won't work because LOOP assumes that TO
> means "count upward."
> 
> The reason for this is that LOOP is a macro.  At compile time, it
> accepts the actual code inside the LOOP form.  Although in your
> example it seems clear that "from 5 to 1 by -1" should step downward,
> this is not the case in general.  For example, you could have the
> following LOOP form: (loop for x from a to b by c ...).  This is a
> perfectly valid LOOP.  The problem is that at compile time, LOOP only
> knows that you are using the variables A, B, and C, but has no way of
> knowing what those variables might contain at runtime.
> 
> Thus:
> 
> (let ((a 3) (b 1) (c -1))
>   (loop for i from a to b by c collect i))
> 
> won't work, because LOOP assumes you want to count upward.  You need
> to specify that you want LOOP to step downward with a DOWNTO clause.

I think it's not the _counting_ part that's hard, it's the comparison
operation. During each iteration the expanded code needs to check the loop
variable against the target value. In the OP's example, :TO indicates that
the target value 5 will be reached from below and hence the comparison
should be done like this: (< i 5) while :DOWNTO would result in (> i 5)

 Cheers, Ralf Mattes
 

> HTH,
> Bill
From: Wade Humeniuk
Subject: Re: Problem while adding -1 in loop
Date: 
Message-ID: <l50Ug.49446$E67.27270@clgrps13>
Mozis wrote:
> Greetings,
> 
> I am newbie to the Lisp and quite a bit in learning phase.
> I had done the following decrement steps,
> 
> (loop for i from 5 to 1 by -1
>     do
>     (print i)
> )
> 
> Answer:
> nil

Change it to

CL-USER 4 > (loop for i from 5 downto 1
                   do (print i))

5
4
3
2
1
NIL

CL-USER 5 >

The above answer immediately terminates because (> 5 1) and that is
the termination condition when iterating up.

Wade