Subject: [clisp-list] scope in loops

From: Pascal Bourguignon <[email-masked]>
Date: Tue Dec 3 00:43:05 2002

Is there any place in HyperSpec  where the scope of the loop variables
is specified?

Consider this loop:

    (loop for ai in a
          for bi in b
          while (eq ai bi)
          finally return (any-lessp ai bi))

In emacs, it  works as expected, but in clisp, we  get this error: "BI
is  neither declared  nor bound,  it  will be  treated as  if it  were
declared SPECIAL." because ai and  bi are not available in the finally
clauses.

Obviously, I expected a loop similar to:

    (do* ( (ap a (cdr ap))
           (ai (car ap) (car ap))
           (bp b (cdr bp)) 
           (bi (car bp) (car bp)) )
        ( (not (and ai bi (eq ai bi)))
          (any-lessp ai bi) )
       )

Since the lists may be of different length, we may be left with no ai,
but still have a bi, and one could  want to be able to process it in a
finally clause, like in with the do* loop.

What's  more, with this  short scope  currently implemented  in clisp,
it's not possible to know what list ended first, so the loop construct
becomes quite impractical.

Could this be considered a defect in the loop implementation of clisp?

(show (macroexpand (quote 

      (loop for ai in a
            for bi in b
            while (eq ai bi)
            finally return (any-lessp ai bi))

            )))

emacs:

(cl-block-wrapper 
 (catch (quote --cl-block-nil--) 
   (let* ((G419505 a)
          (ai nil)
          (G419506 b)
          (bi nil))
     (while (and (consp G419505)
                 (progn (setq ai (car G419505))
                        (consp G419506))
                 (progn (setq bi (car G419506))
                        (eq ai bi)))
       (setq G419505 (cdr G419505))
       (setq G419506 (cdr G419506)))
     (any-lessp ai bi))))

clisp:

(MACROLET ((LOOP-FINISH NIL (SYSTEM::LOOP-FINISH-ERROR)))
 (BLOCK NIL
  (LET NIL
   (LET ((#:G554 A))
    (PROGN
     (LET ((AI NIL))
      (LET ((#:G555 NIL))
       (MACROLET ((LOOP-FINISH NIL '(GO SYSTEM::END-LOOP)))
        (TAGBODY (PROGN (SETQ #:G555 B)) SYSTEM::BEGIN-LOOP
         (PROGN (WHEN (ENDP #:G554) (LOOP-FINISH)) (SETQ AI (CAR #:G554)))
         (PROGN (WHEN (ENDP #:G555) (LOOP-FINISH))
          (LET ((BI (CAR #:G555))) (PROGN (UNLESS (EQ AI BI) (LOOP-FINISH)))))
         (PROGN (PSETQ #:G554 (CDR #:G554)) (PSETQ #:G555 (CDR #:G555)))
         (GO SYSTEM::BEGIN-LOOP) SYSTEM::END-LOOP
         (MACROLET
          ((LOOP-FINISH NIL (SYSTEM::LOOP-FINISH-WARN) '(GO SYSTEM::END-LOOP)))
          (RETURN-FROM NIL (ANY-LESSP AI BI))))))))))))

-- 
__Pascal_Bourguignon__                   http://www.informatimago.com/
----------------------------------------------------------------------
There is no worse tyranny than to force a man to pay for what he does not
want merely because you think it would be good for him.  -- Robert Heinlein

---

From: Sam Steingold <[email-masked]>
Date: Tue Dec 3 09:22:01 2002

> * In message <[email-masked]>
> * On the subject of "[clisp-list] scope in loops"
> * Sent on Tue,  3 Dec 2002 09:41:36 +0100 (CET)
> * Honorable Pascal Bourguignon <[email-masked]> writes:
>

no.  it has been discussed in c.l.l and the consensus appeared to be
that the iteration variables will not necessarily exist inside finally
clauses.

-- 
Sam Steingold (http://www.podval.org/~sds) running RedHat8 GNU/Linux
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.palestine-central.com/links.html>
I don't have an attitude problem. You have a perception problem.

---

From: Sam Steingold <[email-masked]>
Date: Wed Dec 4 15:56:01 2002

> that the iteration variables will not necessarily exist inside finally

nevertheless people do expect the iteration variables to be available
in the finally clauses - and some lisps permit that.

CLISP does not allow (some) iteration variables in the finally clauses
because of the initializations1/initializations2 split in EXPAND-LOOP
(loop.lisp) entitled "Initialisierungen abarbeiten und optimieren".

Removing this optimization results in the same number of bytecodes (15)
and the same speed for
	(defun f1 (a) (loop for x in a sum x))
and 1 less bytecode (25 vs 26) and a marginal (<1%) speed improvement
for 
        (defun f2 (a b) (loop for x in a for y in b sum x sum y))

I think we should remove this optimization.

-- 
Sam Steingold (http://www.podval.org/~sds) running RedHat8 GNU/Linux
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.palestine-central.com/links.html>
char*a="char*a=%c%s%c;main(){printf(a,34,a,34);}";main(){printf(a,34,a,34);}