[iterate-devel] Sequence variables are initialized twice

Hoehle, Joerg-Cyril Joerg-Cyril.Hoehle at t-systems.com
Thu Jun 21 16:20:31 UTC 2007


Bruno Daniel wrote:
>the following example shows that iter initializes
>sequence variables twice, once with 0 and once with
>the start of the range minus 1.

To me this sums up to 2 questions

o Why generate (let ((#:count nil/0)) (setq #:count 5) ...)?

That maybe has to do with an answer to whether the following two expressions
mean the same thing, i.e. whether INITIALLY can still influence
clauses like FOR and REPEAT.
It probably has to do with how Iterate creates bindings. A single LET*
has some restrictions...
(iter (with i = 5) (repeat i) (count t))
(iter (with i) (initially (setq i 5)) (repeat i) (count t))
As I found no place in the documentation about whether or not the latter form
should be supported, I'm somewhat reluctant to change the behaviour.
Iterate is a 18 year old package, so there could be code which depends
on this.
Furthermore, although let + setq does not look pretty, it is possible
that advanced compilers like cmucl and sbcl, which perform some
liveness analysis, will note that the 0 value is thrown away and not
emit code for it.  So performance critical code compiled with
performance enabling compilers does not suffer from that extra
initialization.  CLISP does no such optimization.  I don't know how
others behave.

o Why generate weird code where some initial value is set to 1+ or 1-
what one would expect?
E.g. in (for e in-vector ...), #:index is initialized to -1.
"That breaks type declarations, since one would expect index to be a
positive fixnum."

I believe this is due to the generators.  Drivers are useable as generators, and these are all translated into a sort of (for... (DO-)NEXT body) expression, so that the body can be spliced into the (NEXT ...) clause of a generator case.

In other words, Iterates now deals with code that must produce the initial value upon the first call, e.g. 0 when first called.  To keep the stepper code simple, since it's often nothing more than (incf #:index) with some end-test, the variable is thus initialized with -1, or (1- expression).

Probably it was deemed inacceptable back when that was implemented to make the stepper code more complex, as in (setq index (if (first-time-p) #:initial-index (1+ index))). That for sure is less efficient than a -1 initialization.

Now, I don't know for sure whether that's the only reason for doing so.
One can then claim that if it's the only reason, Iterate could detect whether the clause is actually used as a generator, and produce different code depending on the use as generator or not.  E.g. use -1 with generators, but something like (for x initially 0 then (1+ x)) when not used as generator.


Well, I appreciate that people look closely at what Iterate does, but sometimes I wonder why more people come up with requirements that would make the code even more complex, and fewer people with ideas about how to make it simpler :-)
Still, contributions are welcome!


>Moreover, the declaration is not very tight. dotimes does better
>on SBCL:
>(macroexpand-1 '(dotimes (i 10) (print i)))
>    (DECLARE (TYPE UNSIGNED-BYTE I))
Perhaps because on SBCL, such precise declarations matter, so SBCL goes to
some length to generate them?
At the time Iterate war written, all that mattered was probably FIXNUM, at best.

As far as SBCL is concerned, I'm not even sure such declarations are needed, since one would hope that cmucl/sbcl's type inference system would derive that from the code.  Furthermore, loops with constant bounds are a very special case.  So it's debatable whether to add declarations for such special cases.  Given good type inference, sbcl/cmucl might even be able to infer best types for (repeat <formula>) expressions, and no macro-based package can generate a good type declaration for that.

In short, I think the best place for handling types is the implementation's compiler.  Sort of separation of concerns.
Unless the user knows better than the compiler.  But macro packages do never ever have the user's knowledge.

Regards,
	Jörg Höhle.



More information about the iterate-devel mailing list