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