From: Juanma Barranquero

Subject: Re: loop variable of type real

Date: 1999-5-7 10:19

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Tue, 04 May 1999 09:51:49 -0700, Steve Haflich wrote:

>So, instead the LOOP repeat handler could be tweaked (IMO quite >safely and efficiently) to recognize the common case of an integer >constant in a repeat clause.
I've been reading the CL spec, and it seems to me a bit underspecified regarding the repeat clause of loop (though maybe I've missed something). The relevant fragments I've found are: (At 6.1.1.5.3) "The repeat construct causes termination after a specified number of iterations. (It uses an internal variable to keep track of the number of iterations.)" (At 6.1.2.1) "The iteration control clauses for, as, and repeat must precede any other loop clauses, except initially, with, and named, since they establish variable bindings." (At 6.1.4) "The repeat construct causes iteration to terminate after a specified number of times. The loop body executes n times, where n is the value of the expression form. The form argument is evaluated one time in the loop prologue. If the expression evaluates to 0 or to a negative number, the loop body is not evaluated." (At 6.1.9) "The clause repeat n ... is roughly equivalent to a clause such as (loop for internal-variable downfrom (- n 1) to 0 ...) but in some implementations, the repeat construct might be more efficient." Though there's no information about the allowed type of n, it's obvious that integer is expected, since is impossible to do a fractional number of iterations (not counting premature exits, of course :) OTOH, if I've not missed anything, the standard neither disallows using other sensible values (all other non-integer reals) nor clearly defines what to expect if one is used. For example, are 7.3 iterations 7 or 8? And how about 1/4? Anyway, the bottom line is that, in ACL 5.0, the number of iterations executed is always (ceiling r) for any value r of a type of the real hierarchy, so I've modified the function you already fixed to translate a real number of iterations into an integer one (for a "constantp" number of iterations only, of course). I sure hope I won't be violating my source code license agreement for quoting the code you posted and modifying it...
>(defun loop-do-repeat () > (let ((form (loop-get-form)) > (type (loop-check-data-type (loop-optional-type) *loop-real-data-type*))) > (when (and (consp form) (eq (car form) 'the) (subtypep (second form) type)) > (setq type (second form))) > (multiple-value-bind (number constantp value) > (loop-constant-fold-if-possible form type) > (cond ((and constantp (<= value 1)) `(t () () () ,(<= value 0) () () ())) > (t (WHEN CONSTANTP > (SETQ NUMBER (CEILING VALUE)) > (SETQ TYPE `(INTEGER 0 ,NUMBER))) > (let ((var (loop-make-variable (loop-gentemp 'loop-repeat-) number type))) > (if constantp > `((not (plusp (setq ,var (1- ,var)))) () () () () () () ()) > `((minusp (setq ,var (1- ,var))) () () ()))))))))
And then: USER(6): :ma (loop repeat 10 do t) (LET ((#:G222 10)) (DECLARE (TYPE (INTEGER 0 10) #:G222)) (BLOCK NIL (TAGBODY EXCL::NEXT-LOOP T (WHEN (NOT (PLUSP (SETQ #:G222 (1- #:G222)))) (GO EXCL::END-LOOP)) (GO EXCL::NEXT-LOOP) EXCL::END-LOOP))) USER(7): :ma (loop repeat 9.01 do t) (LET ((#:G223 10)) (DECLARE (TYPE (INTEGER 0 10) #:G223)) (BLOCK NIL (TAGBODY EXCL::NEXT-LOOP T (WHEN (NOT (PLUSP (SETQ #:G223 (1- #:G223)))) (GO EXCL::END-LOOP)) (GO EXCL::NEXT-LOOP) EXCL::END-LOOP))) USER(8): :ma (loop repeat 29/3 do t) (LET ((#:G224 10)) (DECLARE (TYPE (INTEGER 0 10) #:G224)) (BLOCK NIL (TAGBODY EXCL::NEXT-LOOP T (WHEN (NOT (PLUSP (SETQ #:G224 (1- #:G224)))) (GO EXCL::END-LOOP)) (GO EXCL::NEXT-LOOP) EXCL::END-LOOP))) /L/e/k/t/u -----BEGIN PGP SIGNATURE----- Version: PGPfreeware 6.0.2i iQA/AwUBNzLnjf4C0a0jUw5YEQL8dQCgnltt7tXyyCkd9imAOEBDVviXNtUAoI9R 9k3z7mQvniJINZ7Aa/vM1Uy/ =UcUq -----END PGP SIGNATURE-----