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.
"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
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
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.
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
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
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."
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
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