[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RETURN-FROM inside a FINALLY



1) I would like to see NAMED kept as a synonym for putting a
block around the loop, since I hate to break old working
code unnecessarily.

2) It does seem sensible to put the nil block around each loop.
[I don't currently do this for sloop but probably should unless
users could stick to 3)]

3) I would advocate advising users to use loop-return.  I think RETURN
X as a keyword form should be equivalent to (loop-return x).  For
sloop I do recommend using (loop-return x) over (return x).  Since
sloop is quite extensible, users can and do add loop macros or loop
maps where nil would not be an appropriate block name.  There needs to
be a common way of returning from such extensions.  Below are two
examples of actual user extensions, where plain return might be bad.


;;Going through the hash table tab, looking for a value 3.

(sloop for (key val) in-table tab
           when (eql val 3) do (loop-return  ke))
expands to
(MACROLET
    ((LOCAL-FINISH NIL (LIST 'GO '#:FINISH941))
     (LOOP-FINISH NIL (LIST 'GO '#:FINISH941))
     (LOOP-RETURN (&REST SLOOP::VALS)
         (LIST 'RETURN-FROM '#:SLOOP940 (LIST* 'VALUES SLOOP::VALS))))
  (BLOCK #:SLOOP940
    (TAGBODY
      (MAPHASH #'(LAMBDA (KEY VAL)
                   :SLOOP-MAP-DECLARES
                   (PROGN (COND ((EQL KE 3) (LOOP-RETURN KE)))))
               TAB)
      #:FINISH941
      (LOOP-RETURN NIL))))

;; Users definition of IN-TABLE
(def-loop-map in-table (var table)
  `(maphash #'(lambda ,var :sloop-map-declares :sloop-body) ,table))

The maphash might conceivably be implemented in some common lisp so as
to introduce new nil blocks.  It is safer to have our own block.

;; Similarly a user extension IN-FRINGE to loop through the fringe of a tree:

(sloop for v in-fringe tree when (symbolp v) do (loop-return v))

;expands into:
(MACROLET
    ((LOCAL-FINISH NIL (LIST 'GO '#:FINISH937))
     (LOOP-FINISH NIL (LIST 'GO '#:FINISH937))
     (LOOP-RETURN (&REST SLOOP::VALS)
         (LIST 'RETURN-FROM '#:SLOOP936 (LIST* 'VALUES SLOOP::VALS))))
  (BLOCK #:SLOOP936
    (TAGBODY
      (LABELS ((SLOOP::MAP-FRINGE-AUX (SLOOP::.XTREE.)
                   (DO ((#:FINISH935 SLOOP::.XTREE.))
                       ((NULL #:FINISH935))
                     (COND
                       ((ATOM #:FINISH935) (SETF V #:FINISH935)
                        (SETF #:FINISH935 NIL))
                       (T (SETF V (CAR #:FINISH935))
                          (SETF #:FINISH935 (CDR #:FINISH935))))
                     (COND
                       ((NULL V))
                       ((ATOM V) :SLOOP-MAP-DECLARES
                        (PROGN (COND ((SYMBOLP V) (LOOP-RETURN V)))))
                       (T (SLOOP::MAP-FRINGE-AUX V))))))
        (SLOOP::MAP-FRINGE-AUX TREE))
      #:FINISH937
      (LOOP-RETURN NIL))))

This sloop uses a (do (..)..) in its body, which has a nil block.

Bill Schelter


ps:  sloop.lisp is available by anonymous ftp from
rascal.ics.utexas.edu 128.83.144.1