loop conformance

Pascal Costanza pc at p-cos.net
Wed Jan 29 08:04:20 UTC 2014


On 29 Jan 2014, at 02:03, Steve Haflich <shaflich at gmail.com> wrote:

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

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.





More information about the pro mailing list