Discussion:
loop conformance
Steve Haflich
2014-01-29 01:03:07 UTC
Permalink
I'm in a grumpy mood today, so I decided to take out my frustrations on the
ANS for CL, or implementations thereof. Consider carefully what the
following form should return:

(let ((v (make-array 10
:initial-contents '(0 1 2 3 4 5 6 7 8 9)
:fill-pointer 5)))
(loop for x across v
when (eql x 2) do (incf (fill-pointer v))
collect x))

ACL and SBCL both return (0 1 2 3 4). Probably every other implementation
does too. I believe the ANS requires the return to be (0 1 2 3 4 5),
although the definition in *6.1.2.1.5 The for-as-across subclause* uses
various undefined terminology. (We of X3J13 understood that the loop
specification was not our best work.)
Pascal J. Bourguignon
2014-01-29 07:25:52 UTC
Permalink
Post by Steve Haflich
I'm in a grumpy mood today, so I decided to take out my frustrations
on the ANS for CL, or implementations thereof.  Consider carefully
(let ((v (make-array 10
    :initial-contents '(0 1 2 3 4 5 6 7 8 9)
    :fill-pointer 5)))
  (loop for x across v
      when (eql x 2) do (incf (fill-pointer v))
      collect x))
ACL and SBCL both return (0 1 2 3 4).  Probably every other
implementation does too.  I believe the ANS requires the return to be
(0 1 2 3 4 5), although the definition in 6.1.2.1.5 The for-as-across
subclause uses various undefined terminology.  (We of X3J13
understood that the loop specification was not our best work.)
http://www.lispworks.com/documentation/HyperSpec/Body/03_f.htm

Array traversal

For array traversal operations, the array is not allowed to be
adjusted and its fill pointer, if any, is not allowed to be
changed.

So ISTM your code is not conforming, and the result (0 1 2 3 4) seems
reasonable to me, similarly to:

(loop :with max = 10
:for i :from 0 :below max
:do (incf max)
:collect i)
--> (0 1 2 3 4 5 6 7 8 9)




Now, while we have:

(loop :with l = (list 0 1 2 3 4 5 6 7 8 9)
:for x :in l
:when (eql x 2) do (setf (cdr (last l)) (list 10))
:collect x)
--> (0 1 2 3 4 5 6 7 8 9 10)

this is also clearly in contradiction to 3.6 therefore non-conforming
too.
--
__Pascal Bourguignon__
http://www.informatimago.com/
"Le mercure monte ? C'est le moment d'acheter !"
Pascal Costanza
2014-01-29 08:04:20 UTC
Permalink
Post by Steve Haflich
(let ((v (make-array 10
:initial-contents '(0 1 2 3 4 5 6 7 8 9)
:fill-pointer 5)))
(loop for x across v
when (eql x 2) do (incf (fill-pointer v))
collect x))
ACL and SBCL both return (0 1 2 3 4). Probably every other implementation does too. I believe the ANS requires the return to be (0 1 2 3 4 5), although the definition in 6.1.2.1.5 The for-as-across subclause uses various undefined terminology. (We of X3J13 understood that the loop specification was not our best work.)
Don’t write such code. ;)

I recall reading Niklaus Wirth’s explanation why he dropped the FOR statement when moving from Modula-2 to Oberon (“FOR i FROM 0 to n DO …”), the reason being that it’s unclear when the boundaries are reached, and also that it’s unclear what happens when the boundaries have already been reached before the first iteration. He kept only WHILE and REPEAT/UNTIL, because with those statements, it is never ambiguous what you mean.

This is also how I try to use LOOP: If it’s unambiguous what a high-level form could mean, I use it, but otherwise, I switch to a lower-level form, even if the high-level form happens to give me the correct result. I prefer my code to be understandable just from reading it. (I don’t always succeed... ;)


Pascal

--
Pascal Costanza
The views expressed in this email are my own, and not those of my employer.
Jean-Claude Beaudoin
2014-01-29 08:51:39 UTC
Permalink
There is 6.1.1.8 Restrictions on
Side-Effects<http://www.lispworks.com/documentation/HyperSpec/Body/06_aah.htm>that
seems to pretty clearly support the opinion of pjb.
Antoniotti Marco
2014-01-29 08:52:31 UTC
Permalink
Post by Steve Haflich
(We of X3J13 understood that the loop specification was not our best work.)
Shall I utter the P-word? 3:) 3:) 3:) (Or the C-word, and I am sure you agree on this one! :) )

Cheers

MA
Faré
2014-01-29 20:32:11 UTC
Permalink
On Wed, Jan 29, 2014 at 3:52 AM, Antoniotti Marco
Post by Antoniotti Marco
Post by Steve Haflich
(We of X3J13 understood that the loop specification was not our best work.)
Shall I utter the P-word? 3:) 3:) 3:) (Or the C-word, and I am sure you agree on this one! :) )
I'll take the bait.
PATHNAME sounds to me like the obvious horror starting with P — and I
recommend Lispers to give a look at UIOP/PATHNAME to see why.

C, I'm not sure. Looking at the symbol index and glossary, I'll
venture a guess: COMPILER-MACRO?

—♯ƒ • François-René ÐVB Rideau •Reflection&Cybernethics• http://fare.tunes.org
For every complex problem, there is a solution that is simple, neat, and wrong.
— H. L. Mencken
Antoniotti Marco
2014-01-29 20:44:14 UTC
Permalink
Post by Faré
On Wed, Jan 29, 2014 at 3:52 AM, Antoniotti Marco
Post by Antoniotti Marco
Post by Steve Haflich
(We of X3J13 understood that the loop specification was not our best work.)
Shall I utter the P-word? 3:) 3:) 3:) (Or the C-word, and I am sure you agree on this one! :) )
I'll take the bait.
PATHNAME sounds to me like the obvious horror starting with P — and I
recommend Lispers to give a look at UIOP/PATHNAME to see why.
+1 :-)
Post by Faré
C, I'm not sure. Looking at the symbol index and glossary, I'll
venture a guess: COMPILER-MACRO?
Nope. You missed this one!

Does “modern mode" ring a bell? :)

Cheers

MA
Faré
2014-01-29 20:51:23 UTC
Permalink
Post by Antoniotti Marco
Post by Faré
C, I'm not sure. Looking at the symbol index and glossary, I'll
venture a guess: COMPILER-MACRO?
Nope. You missed this one!
Does “modern mode" ring a bell? :)
case sensitive case conversion? Yeah, it's mighty quirky, but it's a
finite amount of brokenness that can be patched over easily and
relatively portably, quite unlike the pathname horror, that reminds me
at a much smaller scale of that description of PHP: "A fractal of bad
design".

—♯ƒ • François-René ÐVB Rideau •Reflection&Cybernethics• http://fare.tunes.org
Schemer: "Buddha is small, clean, and serious."
Lispnik: "Buddha is big, has hairy armpits, and laughs." — Nikodemus Siivola
Antoniotti Marco
2014-01-30 07:25:51 UTC
Permalink
Post by Faré
Post by Antoniotti Marco
Post by Faré
C, I'm not sure. Looking at the symbol index and glossary, I'll
venture a guess: COMPILER-MACRO?
Nope. You missed this one!
Does “modern mode" ring a bell? :)
case sensitive case conversion? Yeah, it's mighty quirky, but it's a
finite amount of brokenness that can be patched over easily and
relatively portably,
Yeah. But go back and check the CLL thread on the introduction of “modern mode” by Franz :)
Post by Faré
quite unlike the pathname horror, that reminds me
at a much smaller scale of that description of PHP: "A fractal of bad
design”.
This I hadn’t heard :) Very nice.

Cheers
--
MA
Post by Faré
—♯ƒ • François-René ÐVB Rideau •Reflection&Cybernethics• http://fare.tunes.org
Schemer: "Buddha is small, clean, and serious."
Lispnik: "Buddha is big, has hairy armpits, and laughs." — Nikodemus Siivola
--
Marco Antoniotti, Associate Professor tel. +39 - 02 64 48 79 01
DISCo, Università Milano Bicocca U14 2043 http://bimib.disco.unimib.it
Viale Sarca 336
I-20126 Milan (MI) ITALY

Please note that I am not checking my Spam-box anymore.
Please do not forward this e
Kenneth Tilton
2014-01-29 20:45:36 UTC
Permalink
Ya gotta love a language and its denizens where the spec is so complete it
either covers feature abuse (see "moving fill pointer during loop-across")
or documents that such abuse is undefined and then said denizens sit around
in pubs ignoring the redhead sitting under the moosehead bemoaning its
inadequacy (the spec, not the moosehead) when it is hard to find a langue
du jour that even has a spec.

If they had not screwed up and called prog0 prog1 I would consider using
the damn thing.

-hp

ps. Are we going to leave Steve off the hook for misreading the spec he
wrote?
Post by Faré
On Wed, Jan 29, 2014 at 3:52 AM, Antoniotti Marco
Post by Antoniotti Marco
Post by Steve Haflich
(We of X3J13 understood that the loop specification was not our best
work.)
Post by Antoniotti Marco
Shall I utter the P-word? 3:) 3:) 3:) (Or the C-word, and I am sure you
agree on this one! :) )
I'll take the bait.
PATHNAME sounds to me like the obvious horror starting with P — and I
recommend Lispers to give a look at UIOP/PATHNAME to see why.
C, I'm not sure. Looking at the symbol index and glossary, I'll
venture a guess: COMPILER-MACRO?
—♯ƒ • François-René ÐVB Rideau •Reflection&Cybernethics•
http://fare.tunes.org
For every complex problem, there is a solution that is simple, neat, and wrong.
— H. L. Mencken
--
Kenneth Tilton
Fort Lauderdale, FL
http://tiltontec.com
http://socialalgebra.com
Pascal J. Bourguignon
2014-01-30 07:57:13 UTC
Permalink
Post by Kenneth Tilton
If they had not screwed up and called prog0 prog1 I would consider
using the damn thing.
They didn't screw up:

(defpackage "KTLISP"
(:use "CL")
(:shadow "PROG1" "PROG2" "PROGN")
(:export "PROG0" "PROGN-1")
(:export . #.(let ((l '()))
(do-external-symbols (s "CL")
(push (symbol-name s) l)) l)))
(in-package "KTLISP")
(defmacro prog0 (&rest body) `(cl:prog1 ,@body))
(defmacro prog1 (&rest body) `(cl:prog2 ,@body))
(defmacro progn-1 (&rest body) `(cl:progn ,@body))
(defmacro progn (&rest body) `(cl:progn ,@body (values)))

(defpackage "KTLISP-USER"
(:use "KTLISP"))

(in-package "KTLISP-USER")

(prog1 'hi '(hello world))
--> (HELLO WORLD)
--
__Pascal Bourguignon__
http://www.informatimago.com/
"Le mercure monte ? C'est le moment d'acheter !"
Loading...