From: Mikalai
Subject: Stylistic question on control transfer (return vs. throw)
Date: 
Message-ID: <1139079070.996681.324710@g14g2000cwa.googlegroups.com>
Hi, everybody,

In CL, a construct (block name ...) with a use of (return-from name
...) inside, looks pretty similar to (catch name ...) with a use of
(throw name ...) inside. They not only look the same, they do pretty
much the same thing - transfering of a control to some specified point,
carrying one piece of info - return result. Blocks, ust like
throw-catchers, can be nested into nested into each other, and the most
resent one will be used. (Yes, there are implicit blocks inside funcs
and do-loop, but these could have easily been catch constructs.)

If these constructs are so similar, then it is only a question of style
to use or another. If so, then what style? What are your suggestions?

From: Ulrich Hobelmann
Subject: Re: Stylistic question on control transfer (return vs. throw)
Date: 
Message-ID: <44kcgdF2jo23U1@individual.net>
Mikalai wrote:
> Hi, everybody,
> 
> In CL, a construct (block name ...) with a use of (return-from name
> ...) inside, looks pretty similar to (catch name ...) with a use of
> (throw name ...) inside. They not only look the same, they do pretty
> much the same thing - transfering of a control to some specified point,
> carrying one piece of info - return result. Blocks, ust like
> throw-catchers, can be nested into nested into each other, and the most
> resent one will be used. (Yes, there are implicit blocks inside funcs
> and do-loop, but these could have easily been catch constructs.)
> 
> If these constructs are so similar, then it is only a question of style
> to use or another. If so, then what style? What are your suggestions?

If you can use return-from, do so.  You don't need to catch anything ;)

-- 
Suffering from Gates-induced brain leakage...
From: Kenny Tilton
Subject: Re: Stylistic question on control transfer (return vs. throw)
Date: 
Message-ID: <Se8Ff.1223$lG2.1135@news-wrt-01.rdc-nyc.rr.com>
Mikalai wrote:
> Hi, everybody,
> 
> In CL, a construct (block name ...) with a use of (return-from name
> ...) inside, looks pretty similar to (catch name ...) with a use of
> (throw name ...) inside. They not only look the same, they do pretty
> much the same thing - transfering of a control to some specified point,
> carrying one piece of info - return result. Blocks, ust like
> throw-catchers, can be nested into nested into each other, and the most
> resent one will be used. (Yes, there are implicit blocks inside funcs
> and do-loop, but these could have easily been catch constructs.)
> 
> If these constructs are so similar, then it is only a question of style
> to use or another. If so, then what style? What are your suggestions?
> 

You found /some/ similarities. You missed some differences.

If I am looking at a throw, I have no idea where it will land, including 
a backtrace. If I am looking at (return-from X...) I know the function 
or block X will simply exit with the value specified.

Then we have dynamic vs lexical, the runtime cost thereof....

Stylistically, one only uses throw in the way one would signal an error. 
ie, You want control to jump from here-and-now to whoever-cares-if-anyone.

kenny
From: Mikalai
Subject: Re: Stylistic question on control transfer (return vs. throw)
Date: 
Message-ID: <1139086346.523526.127590@z14g2000cwz.googlegroups.com>
Kenny Tilton wrote:
>
> You found /some/ similarities. You missed some differences.
>
> If I am looking at a throw, I have no idea where it will land, including
> a backtrace. If I am looking at (return-from X...) I know the function
> or block X will simply exit with the value specified.
>
> Then we have dynamic vs lexical, the runtime cost thereof....
>

That is it.

> Stylistically, one only uses throw in the way one would signal an error.
> ie, You want control to jump from here-and-now to whoever-cares-if-anyone.
> 

OK. Where is it clearer to use throw not an error?
From: Matthew D Swank
Subject: Re: Stylistic question on control transfer (return vs. throw)
Date: 
Message-ID: <pan.2006.02.05.00.18.30.175209@c.net>
On Sat, 04 Feb 2006 12:52:26 -0800, Mikalai wrote:


> OK. Where is it clearer to use throw not an error?

Well if these two papers are any guide*:
  http://www.ccs.neu.edu/home/will/Research/ILC2005/commonLarceny.pdf
  http://home.comcast.net/~prunesquallor/stackhack4.html 
catch and throw could be used in an implementation of first class
continuations.

To Joe Marshall: any thoughts?  

Matt

*I am still trying to digest them.
-- 
"You do not really understand something unless you can
 explain it to your grandmother." — Albert Einstein.
From: Matthew D Swank
Subject: Re: Stylistic question on control transfer (return vs. throw)
Date: 
Message-ID: <pan.2006.02.05.01.12.07.231132@c.net>
On Sat, 04 Feb 2006 18:18:30 -0600, Matthew D Swank wrote:

>   http://www.ccs.neu.edu/home/will/Research/ILC2005/commonLarceny.pdf

should be:

http://www.cs.brown.edu/~sk/Publications/Papers/Published/pcmkf-cont-from-gen-stack-insp/

-- 
"You do not really understand something unless you can
 explain it to your grandmother." — Albert Einstein.
From: Joe Marshall
Subject: Re: Stylistic question on control transfer (return vs. throw)
Date: 
Message-ID: <1139162368.338688.115310@g43g2000cwa.googlegroups.com>
Matthew D Swank wrote:
> On Sat, 04 Feb 2006 12:52:26 -0800, Mikalai wrote:
>
>
> > OK. Where is it clearer to use throw not an error?
>
> Well if these two papers are any guide*:
>   http://www.ccs.neu.edu/home/will/Research/ILC2005/commonLarceny.pdf
>   http://home.comcast.net/~prunesquallor/stackhack4.html
> catch and throw could be used in an implementation of first class
> continuations.
>
> To Joe Marshall: any thoughts?

Lots, but none relevant to the conversation.  Later, maybe.
From: Coby Beck
Subject: Re: Stylistic question on control transfer (return vs. throw)
Date: 
Message-ID: <V79Ff.170417$6K2.3369@edtnps90>
"Mikalai" <········@yahoo.com> wrote in message 
·····························@z14g2000cwz.googlegroups.com...
>
> Kenny Tilton wrote:
>>
>> You found /some/ similarities. You missed some differences.
>>
>> If I am looking at a throw, I have no idea where it will land, including
>> a backtrace. If I am looking at (return-from X...) I know the function
>> or block X will simply exit with the value specified.
>>
>> Then we have dynamic vs lexical, the runtime cost thereof....
>>
>
> That is it.
>
>> Stylistically, one only uses throw in the way one would signal an error.
>> ie, You want control to jump from here-and-now to 
>> whoever-cares-if-anyone.
>>
>
> OK. Where is it clearer to use throw not an error?

Though I would hesitate to extrapolate personal experience to a rule of 
thumb, I have programmed in lisp for about 8 years and 5 companies so far 
and have never used CATCH and THROW.

So never use THROW ;)

-- 
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Kenny Tilton
Subject: Re: Stylistic question on control transfer (return vs. throw)
Date: 
Message-ID: <%I9Ff.274$Lp2.27@news-wrt-01.rdc-nyc.rr.com>
Mikalai wrote:
> Kenny Tilton wrote:
> 
>>You found /some/ similarities. You missed some differences.
>>
>>If I am looking at a throw, I have no idea where it will land, including
>>a backtrace. If I am looking at (return-from X...) I know the function
>>or block X will simply exit with the value specified.
>>
>>Then we have dynamic vs lexical, the runtime cost thereof....
>>
> 
> 
> That is it.
> 
> 
>>Stylistically, one only uses throw in the way one would signal an error.
>>ie, You want control to jump from here-and-now to whoever-cares-if-anyone.
>>
> 
> 
> OK. Where is it clearer to use throw not an error?
> 

When you do not have much information to pass along. Conditions can be 
arranged in a type hierarchy for fancy handling, and can have any number 
of slots.

I might use throw/catch for:

     (catch :user-abort
         <big GUI interaction with many places to abort from>)

I do not even need the throw value. Anyway, no need to define a custom 
condition for this.

ken
From: Larry Clapp
Subject: Re: Stylistic question on control transfer (return vs. throw)
Date: 
Message-ID: <slrnduasav.2kq.larry@theclapp.ddts.net>
On 2006-02-04, Mikalai <········@yahoo.com> wrote:
>> Stylistically, one only uses throw in the way one would signal an
>> error.  ie, You want control to jump from here-and-now to
>> whoever-cares-if-anyone.
>
> OK. Where is it clearer to use throw not an error?

One need not think of catch/throw merely as exception handling by
another name.  Think of it as a non-local return to a dynamically
established (and dynamically named) receiver.

I haven't used catch/throw, but I've seen it used (in slime.el), and I
rather liked it.  Paraphrasing:

(let ((tag (gensym)))
  (apply
    #'funcall
    (catch tag
	   (store-event-handler
	     #'(lambda (event)
		 ; ...
		 (if (ok-p event)
		   (throw tag (list #'identity some-value))
		   (throw tag (list #'error some-error)))))
	   (event-loop)	; never returns
	   )))

STORE-EVENT-HANDLER takes the closure you give it and puts it in a
table.  EVENT-LOOP (surprise) handles events.  Eventually, the
appropriate event comes in, and the closure runs, and it throws one of
two closures out to the catch, which returns it to the apply, which
funcalls it.  If it got a good event, the event handler returns a list
that, when funcalled, returns a value; if it got a bad event (which,
in the natural scheme of things, shouldn't happen), the list, when
funcalled, invokes the debugger.

I hadn't used throw/catch before, so it took me a while to puzzle out
the intent, but when I figured it out, it seemed pretty nifty.

(Note that slime.el is in Emacs Lisp; possibly with Common Lisp you
could do this better some other way.)

-- Larry


p.s. for the real code, see SLIME-EVAL in slime.el.
From: Kaz Kylheku
Subject: Re: Stylistic question on control transfer (return vs. throw)
Date: 
Message-ID: <1139195574.010172.65320@g44g2000cwa.googlegroups.com>
Mikalai wrote:
> Kenny Tilton wrote:
> >
> > You found /some/ similarities. You missed some differences.
> >
> > If I am looking at a throw, I have no idea where it will land, including
> > a backtrace. If I am looking at (return-from X...) I know the function
> > or block X will simply exit with the value specified.
> >
> > Then we have dynamic vs lexical, the runtime cost thereof....
> >
>
> That is it.
>
> > Stylistically, one only uses throw in the way one would signal an error.
> > ie, You want control to jump from here-and-now to whoever-cares-if-anyone.
> >
>
> OK. Where is it clearer to use throw not an error?

Here is one situation. I have used THROW in order to define a protocol
for bailing out of self-contained body of code after all internal error
handling has failed. So the situation was no longer an error, just the
ultimate escape mechanism. The THROW is what a catch-all error hander
would do if it could not find a suitable restart.

The outer wrapper would just exit to the operating system with a
termination status. But I did not want to scatter these exit calls
throughout the code, because unwinding would not take place.

INVOKE-RESTART could have been used also, but THROW and CATCH quite
simply have simpler syntactic sugar.

In Lisp, dynamic non-local returns aren't used for error situations:
conditions are. A dynamic return is done as the last step, when error
handling has been settled.

Normally, this is done with restarts.

A simple catch can be used as a restart when you don't need the ability
of being able to determine whether a restart is available; it's trusted
to just be there.

With restarts, you can enumerate available restarts, determine whether
a particular restart is available, making restarts invisible based on
logical conditions and such.

There are probably overheads in restarts compared to catches for all
these added capabilities.
From: Alan Crowe
Subject: Re: Stylistic question on control transfer (return vs. throw)
Date: 
Message-ID: <86vevs1ba6.fsf@cawtech.freeserve.co.uk>
"Mikalai" <········@yahoo.com> asks:
> OK. Where is it clearer to use throw not an error?

You can write a function that copies a list, cutting out the
bits between repeated symbols. With catch and throw it looks
like this:

CL-USER> (defun cut-out (list seen)
           (cond ((endp list) nil)
                 ((find (car list) seen)
                  (throw (car list)
                    (cut-out (cdr list)
                             (remove (car list)
                                     seen))))
                 (t (catch (car list)
                      (cons (car list)
                            (cut-out (cdr list)
                                     (cons (car list)
                                           seen)))))))
=> CUT-OUT

CL-USER> (cut-out '(we want to omit from here all the way to here
                    and skip everything between the skip
                    symbols)
                  '())
=> (WE WANT TO OMIT FROM AND SYMBOLS)

Which raises two questions:

1)How else might one code this?

2)Does this kind of thing ever arise in practise?

Alan Crowe
Edinbrugh
Scotland
From: ····@unreal.uncom
Subject: Re: Stylistic question on control transfer (return vs. throw)
Date: 
Message-ID: <cu7gu1t36mhljjds28j9rmin3gnpjqhmro@4ax.com>
On 06 Feb 2006 20:29:21 +0000, Alan Crowe
<····@cawtech.freeserve.co.uk> wrote:

>CL-USER> (cut-out '(we want to omit from here all the way to here
>                    and skip everything between the skip
>                    symbols)
>                  '())
>=> (WE WANT TO OMIT FROM AND SYMBOLS)

Shouldn't it omit everything between the 2 TO's?

>1)How else might one code this?

(defun cut-out (list)
  (when list
    (let* ((a (car list))
           (b (cdr list))
           (c (member a b)))
      (if c (cut-out (cdr c))
        (cons a (cut-out b))))))
From: Kaz Kylheku
Subject: Re: Stylistic question on control transfer (return vs. throw)
Date: 
Message-ID: <1139298250.596217.171460@o13g2000cwo.googlegroups.com>
····@unreal.uncom wrote:
> On 06 Feb 2006 20:29:21 +0000, Alan Crowe
> <····@cawtech.freeserve.co.uk> wrote:
>
> >CL-USER> (cut-out '(we want to omit from here all the way to here
> >                    and skip everything between the skip
> >                    symbols)
> >                  '())
> >=> (WE WANT TO OMIT FROM AND SYMBOLS)
>
> Shouldn't it omit everything between the 2 TO's?

Not if it processes the list backwards, looking for rightmost
reductions rather than leftmost ones. The HERE ... HERE reduction will
eat the second TO, leaving no match for the first one.
From: Pascal Bourguignon
Subject: Re: Stylistic question on control transfer (return vs. throw)
Date: 
Message-ID: <87fymvqoyu.fsf@thalassa.informatimago.com>
····@unreal.uncom writes:

> On 06 Feb 2006 20:29:21 +0000, Alan Crowe
> <····@cawtech.freeserve.co.uk> wrote:
>
>>CL-USER> (cut-out '(we want to omit from here all the way to here
>>                    and skip everything between the skip
>>                    symbols)
>>                  '())
>>=> (WE WANT TO OMIT FROM AND SYMBOLS)
>
> Shouldn't it omit everything between the 2 TO's?
>
>>1)How else might one code this?
>
> (defun cut-out (list)
>   (when list
>     (let* ((a (car list))
>            (b (cdr list))
>            (c (member a b)))
>       (if c (cut-out (cdr c))
>         (cons a (cut-out b))))))

What about some basic testing?


(defun cut-out-1 (list seen)
           (cond ((endp list) nil)
                 ((find (car list) seen)
                  (throw (car list)
                    (cut-out-1 (cdr list)
                             (remove (car list)
                                     seen))))
                 (t (catch (car list)
                      (cons (car list)
                            (cut-out-1 (cdr list)
                                     (cons (car list)
                                           seen)))))))

(defun cut-out-2 (list &optional ignore)
  (declare (ignore ignore))
  (when list
    (let* ((a (car list))
           (b (cdr list))
           (c (member a b)))
      (if c (cut-out-2 (cdr c))
        (cons a (cut-out-2 b))))))

(mapcar
  (lambda (cut-out) 
  (funcall cut-out '(we want to omit from here all the way to here
                     and skip everything between the skip
                     symbols) '())) 
  '(cut-out-1 cut-out-2))
-->
((WE WANT TO OMIT FROM AND SYMBOLS)
 (WE WANT HERE AND SYMBOLS))

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

"Our users will know fear and cower before our software! Ship it!
Ship it and let them flee like the dogs they are!"
From: Rob Warnock
Subject: Re: Stylistic question on control transfer (return vs. throw)
Date: 
Message-ID: <BK2dnVHrb4HnxnTenZ2dnUVZ_sWdnZ2d@speakeasy.net>
Pascal Bourguignon  <······@informatimago.com> wrote:
+---------------
| What about some basic testing?
...
| ((WE WANT TO OMIT FROM AND SYMBOLS)
|  (WE WANT HERE AND SYMBOLS))
+---------------

IMHO the initial problem specification [absent using the
initially-presented solution as code-as-specification]
was too vague to be able to distinguish between those
solutions. It also failed to specify what should be done
with *three* (or any odd number) of an item, or with more
than one pair (any even number >2) of the same item.
As someone else said, absent such a spec, both greedy
and non-greedy algorithms could be valid, and both
left-to-right and right-to-left algorithms could be valid.

But then, this group certainly knows that a comprehensive
spec is much harder than a singleton implementation...  ;-}  ;-}


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Pascal Bourguignon
Subject: Re: Stylistic question on control transfer (return vs. throw)
Date: 
Message-ID: <87hd7am42d.fsf@thalassa.informatimago.com>
····@rpw3.org (Rob Warnock) writes:

> Pascal Bourguignon  <······@informatimago.com> wrote:
> +---------------
> | What about some basic testing?
> ...
> | ((WE WANT TO OMIT FROM AND SYMBOLS)
> |  (WE WANT HERE AND SYMBOLS))
> +---------------
>
> IMHO the initial problem specification [absent using the
> initially-presented solution as code-as-specification]
> was too vague to be able to distinguish between those
> solutions. 

The initial problem was fully and formally specified, as source code.

> It also failed to specify what should be done
> with *three* (or any odd number) of an item, or with more
> than one pair (any even number >2) of the same item.
> As someone else said, absent such a spec, both greedy
> and non-greedy algorithms could be valid, and both
> left-to-right and right-to-left algorithms could be valid.
>
> But then, this group certainly knows that a comprehensive
> spec is much harder than a singleton implementation...  ;-}  ;-}

But I otherwise agree, source code often overspecify, and you can only
maintain it bug for bug...

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

WARNING: This product warps space and time in its vicinity.
From: Alan Crowe
Subject: Re: Stylistic question on control transfer (return vs. throw)
Date: 
Message-ID: <86slqv3w3w.fsf@cawtech.freeserve.co.uk>
····@unreal.uncom writes:
> On 06 Feb 2006 20:29:21 +0000, Alan Crowe
> <····@cawtech.freeserve.co.uk> wrote:
> 
> >CL-USER> (cut-out '(we want to omit from here all the way to here
> >                    and skip everything between the skip
> >                    symbols)
> >                  '())
> >=> (WE WANT TO OMIT FROM AND SYMBOLS)
> 
> Shouldn't it omit everything between the 2 TO's?
> 
> >1)How else might one code this?
> 
> (defun cut-out (list)
>   (when list
>     (let* ((a (car list))
>            (b (cdr list))
>            (c (member a b)))
>       (if c (cut-out (cdr c))
>         (cons a (cut-out b))))))

This post was a big shock to me. I had intended that my code
process the list left to right, but hadn't spotted the two
`to's in my test case, so I thought the code had passed.

As Kaz points out, its is an ebb versus flood thing.

CL-USER> (defun starts-with (tag list)
           (if (eql tag (car list))
               list
               nil))
STARTS-WITH
CL-USER> (defun member-flood (item list)
           (and list
                (or (starts-with item list)
                    (member-flood item (cdr list)))))
MEMBER-FLOOD
CL-USER> (member-flood 3 '(1 2 3 4 5 4 3 2 1))
(3 4 5 4 3 2 1)
CL-USER> (defun member-ebb (item list)
           (and list
                (or (member-ebb item (cdr list))
                    (starts-with item list))))
MEMBER-EBB
CL-USER> (member-ebb 3 '(1 2 3 4 5 4 3 2 1))
(3 2 1)

I was imagining that THROW unwinds the stack to the tag
before evaluating the expression it contains, but infact it
works more like a function, evaluating the internal
expression first, with the result that the list is processed
on the ebb, ie backwards.

So I've learned more about catch and throw from
participating in this thread. However, the example I was so
proud of doesn't look so good any more.

Does anyone have a convincing example of catch and throw
with run time computation of tags that is an actual
algorithm and not just error handling?

Alan Crowe
Edinburgh
Scotland
From: Kaz Kylheku
Subject: Re: Stylistic question on control transfer (return vs. throw)
Date: 
Message-ID: <1139338957.483650.163970@g14g2000cwa.googlegroups.com>
Alan Crowe wrote:
> ····@unreal.uncom writes:
> > On 06 Feb 2006 20:29:21 +0000, Alan Crowe
> > <····@cawtech.freeserve.co.uk> wrote:
> >
> > >CL-USER> (cut-out '(we want to omit from here all the way to here
> > >                    and skip everything between the skip
> > >                    symbols)
> > >                  '())
> > >=> (WE WANT TO OMIT FROM AND SYMBOLS)
> >
> > Shouldn't it omit everything between the 2 TO's?
> >
> > >1)How else might one code this?
> >
> > (defun cut-out (list)
> >   (when list
> >     (let* ((a (car list))
> >            (b (cdr list))
> >            (c (member a b)))
> >       (if c (cut-out (cdr c))
> >         (cons a (cut-out b))))))
>
> This post was a big shock to me. I had intended that my code
> process the list left to right, but hadn't spotted the two
> `to's in my test case, so I thought the code had passed.

Left to right isn't necessarily any better than right to left.

If the problem specification were to say that instances such as

  FOO .... BAR .... FOO  .... BAR

must result in a complete deletion from the first FOO to the last BAR,
then neither approach is satisfactory.

What you must do is, quite probably, make two passes. In the first
pass, tag all elements of the list which fall between two identical
words, including the words themselves. Then, in a second pass, remove
all tagged elements.

One way to do this might be to scan the list left to right. Whenever a
symbol is encountered, begin a "scope" and retain the location. When
the same symbol is encountered again, close the scope. Iterate from the
saved pointer to the current location, and tag the items for removal.

A hash can be used to tag the conses to be removed. The scoping stuff
can be handled through property lists.

(defun cut-out (list-of-syms)
  (let ((remove-tag-hash (make-hash-table :test #'eq)))
    ;;; pass one, clear :scope property from symbols
    (dolist (sym list-of-syms)
      (remprop sym :scope))

    ;;; pass two, determine symbols to delete
    (loop for cell = list-of-syms then (cdr cell)
          for sym = (car cell)
          for start = (get sym :scope)
          until (null cell)
          do (if start
               (progn
                 (remprop sym :scope)
                 (loop for mark = start then (cdr mark)
                       do (setf (gethash mark remove-tag-hash) t)
                       until (eq mark cell)))
               (setf (get sym :scope) cell)))

    ;;; pass three, delete them. (Actually, make a new list which
copies
    ;;; only the items from unmarked cells).
    (loop for cell = list-of-syms then (cdr cell)
          until (null cell)
          unless (gethash cell remove-tag-hash)
            collect (car cell) into new-list
          finally return new-list)))
From: Brian Downing
Subject: Re: Stylistic question on control transfer (return vs. throw)
Date: 
Message-ID: <ou5Gf.782312$xm3.684210@attbi_s21>
In article <··············@cawtech.freeserve.co.uk>,
Alan Crowe  <····@cawtech.freeserve.co.uk> wrote:
> So I've learned more about catch and throw from
> participating in this thread. However, the example I was so
> proud of doesn't look so good any more.
> 
> Does anyone have a convincing example of catch and throw
> with run time computation of tags that is an actual
> algorithm and not just error handling?

One problem is that most cases where you might want runtime-computed
throw and catch tags are more cleanly handled with either TAGBODY/GO
or BLOCK/RETURN-FROM.  See a typical macroexpansion of HANDLER-CASE or
RESTART-CASE for an example:

(handler-case
    (error "error")
  (error (c)
    (format t "whoops: ~A~%" c))
  (condition (c)
    (blort)))

(BLOCK #:G1234
  (LET ((#:G1235 NIL))
    (DECLARE (IGNORABLE #:G1235))
    (TAGBODY
       (HANDLER-BIND
           ((ERROR (LAMBDA (SB-IMPL::TEMP)
                     (SETQ #:G1235 SB-IMPL::TEMP)
                     (GO #:G1236)))
            (CONDITION (LAMBDA (SB-IMPL::TEMP)
                         (SETQ #:G1235 SB-IMPL::TEMP)
                         (GO #:G1237))))
         (RETURN-FROM #:G1234
           (MULTIPLE-VALUE-PROG1 (ERROR "error")
             (SB-KERNEL:FLOAT-WAIT))))
     #:G1236
       (RETURN-FROM #:G1234
         (LET ((C #:G1235))
           (FORMAT T "whoops: ~A~%" C)))
     #:G1237
       (RETURN-FROM #:G1234
         (LET ((C #:G1235))
           (BLORT))))))

If GO and RETURN-FROM couldn't unwind the stack, this would need to be
done with a computed THROW.

-bcd
-- 
*** Brian Downing <bdowning at lavos dot net> 
From: Bulent Murtezaoglu
Subject: Re: Stylistic question on control transfer (return vs. throw)
Date: 
Message-ID: <87y80rx86s.fsf@p4.internal>
>>>>> "M" == Mikalai  <········@yahoo.com> writes:
[...]
    M> If these constructs are so similar, then it is only a question
    M> of style to use or another. If so, then what style? What are
    M> your suggestions?

It is not so.  I quote:

"catch differs from block in that catch tags have dynamic scope while block 
names have lexical scope."

from: http://www.lispworks.com/documentation/HyperSpec/Body/s_catch.htm#catch

cheers,

BM
From: Harald Hanche-Olsen
Subject: Re: Stylistic question on control transfer (return vs. throw)
Date: 
Message-ID: <pcolkwqq49b.fsf@shuttle.math.ntnu.no>
+ Bulent Murtezaoglu <··@acm.org>:

| It is not so.  I quote:
|
| "catch differs from block in that catch tags have dynamic scope
| while block names have lexical scope."

From which, one could add, we deduce that there is likely to be an
overhead associated with a throw (search the stack for a catch tag)
that is not there in case of a return (single instruction).

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- It is undesirable to believe a proposition
  when there is no ground whatsoever for supposing it is true.
  -- Bertrand Russell
From: Kaz Kylheku
Subject: Re: Stylistic question on control transfer (return vs. throw)
Date: 
Message-ID: <1139194573.628761.17180@f14g2000cwb.googlegroups.com>
Mikalai wrote:
> Hi, everybody,
>
> In CL, a construct (block name ...) with a use of (return-from name
> ...) inside, looks pretty similar to (catch name ...) with a use of
> (throw name ...) inside. They not only look the same, they do pretty
> much the same thing - transfering of a control to some specified point,
> carrying one piece of info - return result.

Except that block names establish /static/ return points, whereas catch
tags are /dynamic/ return points. You cannot perform a (RETURN-FROM
FOO) that is not enclosed in a (BLOCK FOO ...).

A (THROW 'FOO) only needs to be within the dynamic contour of a (CATCH
'FOO ...).

This means that a THROW is a dynamic non-local control transfer,
whereas a RETURN-FROM isn't.

> If these constructs are so similar, then it is only a question of style
> to use or another. If so, then what style? What are your suggestions?

The static versus dynamic semantic distinction is serious enough that
the choice is more than a matter of style.

A RETURN-FROM cannot escape out of a closure body. A THROW can, but to
a CATCH that is set up by the caller (around the FUNCALL or whatever),
not necessarily one that is or was set up in the environment that
surrounded the creation of the closure.
From: Peter Seibel
Subject: Re: Stylistic question on control transfer (return vs. throw)
Date: 
Message-ID: <m2bqxl9ofi.fsf@gigamonkeys.com>
"Kaz Kylheku" <········@gmail.com> writes:

> A RETURN-FROM cannot escape out of a closure body. 

Except, as I'm sure Kaz knows, in the case where the RETURN-FROM in
the closure is returning to a BLOCK established outside the closure.
In which case the closure must be invoked within the dynamic extent of
the BLOCK. E.g.

  (defun bar (fn) (funcall fn))

  (defun foo ()
    (block my-block
      (bar #'(lambda ()
               (return-from my-block 'whatever)
               (print "won't see this")))
      (print "nor this")))

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: Brian Downing
Subject: Re: Stylistic question on control transfer (return vs. throw)
Date: 
Message-ID: <A5zFf.536050$084.279023@attbi_s22>
In article <·······················@f14g2000cwb.googlegroups.com>,
Kaz Kylheku <········@gmail.com> wrote:
> Except that block names establish /static/ return points, whereas catch
> tags are /dynamic/ return points. You cannot perform a (RETURN-FROM
> FOO) that is not enclosed in a (BLOCK FOO ...).

> A RETURN-FROM cannot escape out of a closure body. A THROW can, but to
> a CATCH that is set up by the caller (around the FUNCALL or whatever),
> not necessarily one that is or was set up in the environment that
> surrounded the creation of the closure.

Blocks and tags do have lexical scope, but they can escape out of a
closure body:

CL-USER> (progn
           (block out
             (labels ((spew (n)
                        (when (> n 10) (return-from out))
                        (print n)
                        (spew (1+ n))))
               (spew 3)))
           (print 'done))

3 
4 
5 
6 
7 
8 
9 
10 
DONE

-bcd
-- 
*** Brian Downing <bdowning at lavos dot net>