From: Madhu
Subject: 2 Comments regarding restarts in the CL Condition system
Date: 
Message-ID: <m3ejpi75za.fsf@robolove.meer.net>
Helu, I'd like to pose the following two points that I understand of
the condition system --

1. The restart function (i.e. the code executed when the restart is
   invoked) does not have access to the condition object that
   triggered it.  (The condition object which is available to the
   :test function supplied in RESTART-CASE, for example)

2. The interfaces to specifying restarts are all
   macros. (WITH-SIMPLE-RESTART, RESTART-BIND, RESTART-CASE, and
   possibly WITH-CONDITION-RESTARTS)

Re (1), it would seem desirable to have the condition object made
available to the restart code when invoked.  (2) means there is no
functional interface (i.e. via functions) to specifying restarts
objects, and this would seem to imply one cannot programatically
create "condtion-handling-environments" at runtime --- without
recourse to EVAL or a bulky compile. (I suspect This issue is similar
to TRACE being a macro.)

It appears both (1) and (2) are related, and are artifacts of
`implementing' properties desired in the restart objects: that they
can be passed around and invoked.

Could a future design, in theory, remove both limitations (if i may
call them limitations), or is there any basic reason why (1) and (2)
should be this way?

--
Madhu

From: Kaz Kylheku
Subject: Re: 2 Comments regarding restarts in the CL Condition system
Date: 
Message-ID: <1169790312.605051.177960@s48g2000cws.googlegroups.com>
On Jan 25, 8:43 pm, Madhu <·······@meer.net> wrote:
> Helu, I'd like to pose the following two points that I understand of
> the condition system --
>
> 1. The restart function (i.e. the code executed when the restart is
>    invoked) does not have access to the condition object that
>    triggered it.

A restart is not triggered by a condition. It's triggered by
INVOKE-RESTART, or a restart function based on it. INVOKE-RESTART can
pass arbitrary arguments to the restart, which is why it takes &REST
parameters. INVOKE-RESTART can be used in the absence of any condition.
Just set up a restart, and invoke it.

  ;; use restarts like THROW and CATCH
  (restart-case (invoke-restart 'catch 42) (catch (it) (print it)))

A restart is usually called by a handler. It can return to the handler,
but usually, a restart performs a non-local control transfer, which
causes the condition to be handled. (Because this final non-local
transfer the usual path, the RESTART-CASE macro is provided to simplify
coding it).

A handler can certainly pass the condition to the restart; it's just
that this has to be explicitly coded by you. There is no implicit
universal access to the ongoing condition.

But in general, handlers know something about a restart they invoke,
since it's selected for a reason. If some restart is developed which
does something useful with a condition object, then you'd ensure that
your handler passes that condition when invoking that restart. Just
like if you were using some library function which takes a certain type
of argument, you'd supply that argument.

 (The condition object which is available to the
>    :test function supplied in RESTART-CASE, for example)
>
> 2. The interfaces to specifying restarts are all
>    macros. (WITH-SIMPLE-RESTART, RESTART-BIND, RESTART-CASE, and
>    possibly WITH-CONDITION-RESTARTS)

These have to be special forms because the environment has to be
manipulated to set up restarts. A function call cannot set up a binding
in the calling environment.

To an extent, you can fake the apperance of dynamically inserting a
restart, by using the feature of conditionally making restarts visible
(for instance by using this :TEST in RESTART-CASE that you mention
above).

> (2) means there is no functional interface (i.e. via functions) to specifying restarts
> objects, and this would seem to imply one cannot programatically
> create "condtion-handling-environments" at runtime --- without
> recourse to EVAL or a bulky compile.

I don't see how this could work realistically. You're looking at a
function that twiddles things in up in your own stack frames. ``Gee, I
wish there were some restarts in my calling frame; let's poke them in
somehow. No space? We will just resize the stack frame, adjust a bunch
of link pointers, and squeeze them in.''

Sure, software is infinitely malleable so just about anything you can
dream of can be implemented if you just pile enough hacks on top of
other hacks, and debug everything.

Note that you can't introduce new lexical bindings at run-time either.
Is that an implementation limitation, or a fundamental artifact of how
lexical scope works? It's a price we pay for having lexical scopes
baked into efficient machine code, but on the other hand, that can be
used as an excuse for any inflexibility whatsoever, including
application development in assembly language.

> (I suspect This issue is similar
> to TRACE being a macro.)

This probably has to do so that tracing of lexical functions can be
supported. For just top-level functions, there is little reason for
TRACE to be a macro operator, other than the convenience of not having
to quote the symbols.
From: Barry Margolin
Subject: Re: 2 Comments regarding restarts in the CL Condition system
Date: 
Message-ID: <barmar-16A003.01343526012007@comcast.dca.giganews.com>
In article <························@s48g2000cws.googlegroups.com>,
 "Kaz Kylheku" <········@gmail.com> wrote:

> On Jan 25, 8:43 pm, Madhu <·······@meer.net> wrote:
> > (2) means there is no functional interface (i.e. via functions) to 
> > specifying restarts
> > objects, and this would seem to imply one cannot programatically
> > create "condtion-handling-environments" at runtime --- without
> > recourse to EVAL or a bulky compile.
> 
> I don't see how this could work realistically. You're looking at a
> function that twiddles things in up in your own stack frames. ``Gee, I
> wish there were some restarts in my calling frame; let's poke them in
> somehow. No space? We will just resize the stack frame, adjust a bunch
> of link pointers, and squeeze them in.''

Since posting my reply, in which I said something similar to you, I've 
changed my mind.

Since restarts live in the dynamic environment, not the lexical 
environment, they could be established by functions, as long as the 
function takes a continuation function to execute in the environment of 
the restarts.  The continuation function is how it avoids the problem 
you describe, of needing to smash the current stack frame.

It's very likely that restarts are implemented simply by binding a 
special variable.  So call-with-restart might be implemented as 
something like:

(defun call-with-restart (restart-name restart-func continuation &rest 
keyword-options)
  (let ((*restarts* (cons (list* restart-name 
                                 restart-func keyword-options)
                          *restarts*)))
    (funcall continuation)))

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Harald Hanche-Olsen
Subject: Re: 2 Comments regarding restarts in the CL Condition system
Date: 
Message-ID: <pcotzye6qxy.fsf@shuttle.math.ntnu.no>
+ "Kaz Kylheku" <········@gmail.com>:

|   (restart-case (invoke-restart 'catch 42) (catch (it) (print it)))

Of course, the correct value for this example is 22, not 42.

But thanks for the tutorial, anyhow.

It made me realize I haven't really grokked restarts yet.

-- 
* 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: Barry Margolin
Subject: Re: 2 Comments regarding restarts in the CL Condition system
Date: 
Message-ID: <barmar-944140.00530426012007@comcast.dca.giganews.com>
In article <··············@robolove.meer.net>, Madhu <·······@meer.net> 
wrote:

> Helu, I'd like to pose the following two points that I understand of
> the condition system --
> 
> 1. The restart function (i.e. the code executed when the restart is
>    invoked) does not have access to the condition object that
>    triggered it.  (The condition object which is available to the
>    :test function supplied in RESTART-CASE, for example)
> 
> 2. The interfaces to specifying restarts are all
>    macros. (WITH-SIMPLE-RESTART, RESTART-BIND, RESTART-CASE, and
>    possibly WITH-CONDITION-RESTARTS)
> 
> Re (1), it would seem desirable to have the condition object made
> available to the restart code when invoked.  (2) means there is no

Why do you think you need this?  What kinds of restarts do you envision 
that need to know why they were invoked?

> functional interface (i.e. via functions) to specifying restarts
> objects, and this would seem to imply one cannot programatically
> create "condtion-handling-environments" at runtime --- without
> recourse to EVAL or a bulky compile. (I suspect This issue is similar
> to TRACE being a macro.)

Since establishing restarts manipulates the stack, they need to expand 
into special operators.  There aren't functional equivalents for the 
same reason that there's no functional equivalent to LET.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Rob Warnock
Subject: LET <==> LAMBDA  [was: Re: 2 Comments regarding restarts...]
Date: 
Message-ID: <AL6dnabnY98BXiTYnZ2dnUVZ_vOlnZ2d@speakeasy.net>
Barry Margolin <······@alum.mit.edu> wrote:
+---------------
| Since establishing restarts manipulates the stack, they need to expand 
| into special operators.  There aren't functional equivalents for the 
| same reason that there's no functional equivalent to LET.
+---------------

Actually, isn't LET just syntactic sugar around LAMBDA?

    > (defmacro my-let ((&rest bindings) &body body)
	(let ((vars (mapcar #'car bindings))
	      (vals (mapcar #'cadr bindings)))
	  `((lambda ,vars ,@body) ,@vals)))

    MY-LET
    > (macroexpand-1
       '(my-let ((x 2) (y 3))
	  (+ x (* y 5))))

    ((LAMBDA (X Y) (+ X (* Y 5))) 2 3)
    T
    > (my-let ((x 2) (y 3))
	(+ x (* y 5)))

    17
    > 


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Harald Hanche-Olsen
Subject: Re: LET <==> LAMBDA
Date: 
Message-ID: <pcops926qss.fsf@shuttle.math.ntnu.no>
+ ····@rpw3.org (Rob Warnock):

| Barry Margolin <······@alum.mit.edu> wrote:
| +---------------
| | Since establishing restarts manipulates the stack, they need to expand 
| | into special operators.  There aren't functional equivalents for the 
| | same reason that there's no functional equivalent to LET.
| +---------------
|
| Actually, isn't LET just syntactic sugar around LAMBDA?

I'm sure it could be.  But lambda isn't a function either, so what's
your point?

-- 
* 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: Rob Warnock
Subject: Re: LET <==> LAMBDA
Date: 
Message-ID: <pb-dnaZ6ooB7aSTYnZ2dnUVZ_s6onZ2d@speakeasy.net>
Harald Hanche-Olsen  <······@math.ntnu.no> wrote:
+---------------
| + ····@rpw3.org (Rob Warnock):
| | Barry Margolin <······@alum.mit.edu> wrote:
| | +---------------
| | | Since establishing restarts manipulates the stack, they need to expand 
| | | into special operators.  There aren't functional equivalents for the 
| | | same reason that there's no functional equivalent to LET.
| | +---------------
| |
| | Actually, isn't LET just syntactic sugar around LAMBDA?
| 
| I'm sure it could be.  But lambda isn't a function either, so what's
| your point?
+---------------

That unlike restarts, which have to play whack-a-stack under the
covers and are thus something a user can't implement with functions,
LET *is* something that a user can implement directly in terms of
function calls [albeit however ugly it might be without macros].
The fact that LAMBDA is also a special form is not an issue here,
since without LAMBDA you don't even *have* functions.

Never mind, it was only a minor nit about the tail of Barry's post...


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Barry Margolin
Subject: Re: LET <==> LAMBDA
Date: 
Message-ID: <barmar-13D565.16582827012007@comcast.dca.giganews.com>
In article <································@speakeasy.net>,
 ····@rpw3.org (Rob Warnock) wrote:

> Harald Hanche-Olsen  <······@math.ntnu.no> wrote:
> +---------------
> | + ····@rpw3.org (Rob Warnock):
> | | Barry Margolin <······@alum.mit.edu> wrote:
> | | +---------------
> | | | Since establishing restarts manipulates the stack, they need to expand 
> | | | into special operators.  There aren't functional equivalents for the 
> | | | same reason that there's no functional equivalent to LET.
> | | +---------------
> | |
> | | Actually, isn't LET just syntactic sugar around LAMBDA?
> | 
> | I'm sure it could be.  But lambda isn't a function either, so what's
> | your point?
> +---------------
> 
> That unlike restarts, which have to play whack-a-stack under the
> covers and are thus something a user can't implement with functions,
> LET *is* something that a user can implement directly in terms of
> function calls [albeit however ugly it might be without macros].

Not really.  Since LAMBDA requires the variables to be bound to be 
specified statically, just like LET, they're isomorphic.  There's no 
function you can call and pass variable names to be bound as in a LET or 
LAMBDA.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Madhu
Subject: Re: 2 Comments regarding restarts in the CL Condition system
Date: 
Message-ID: <m3ac066uft.fsf@robolove.meer.net>
* Barry Margolin <····························@comcast.dca.giganews.com> :

|> Re (1), it would seem desirable to have the condition object made
|> available to the restart code when invoked.  (2) means there is no
|
| Why do you think you need this?  What kinds of restarts do you envision 
| that need to know why they were invoked?

Condition objects can carry state information (from the point at which
where they were thrown). A restart might need to use such state
information. It could just get them from the condition slots if
available. Otherwise INVOKE-RESTART will have to get that information
through some other means (by mutating the dynamic environment, or
prompting the user again)

Although a restart is invoked by INVOKE-RESTART, I was (perhaps
mistakenly) assuming that there is always one condition active at any
time which triggers the situation leading to its invocation, and which
could be exposed. Even if one were several debug levels deep, there
would be a notion of "current condition being handled", (which is what
I wanted)

The restart may of course do anything --- including getting rid of the
other conditions on the debug stack, so I'm not sure if this is a
valid notion in general.

--
Madhu
From: Kaz Kylheku
Subject: Re: 2 Comments regarding restarts in the CL Condition system
Date: 
Message-ID: <1169940546.396998.207830@k78g2000cwa.googlegroups.com>
On Jan 26, 12:52 am, Madhu <·······@meer.net> wrote:
> * Barry Margolin <····························@comcast.dca.giganews.com> :
>
> |> Re (1), it would seem desirable to have the condition object made
> |> available to the restart code when invoked.  (2) means there is no
> |
> | Why do you think you need this?  What kinds of restarts do you envision
> | that need to know why they were invoked?
>
> Condition objects can carry state information (from the point at which
> where they were thrown). A restart might need to use such state
> information.

Strictly speaking, a restart has nothing to do with conditions. You 
can invoke restarts in the absence of any condition handling.

> It could just get them from the condition slots if
> available. Otherwise INVOKE-RESTART will have to get that information
> through some other means (by mutating the dynamic environment, or
> prompting the user again)

In an earlier reply, I pointed out that INVOKE-RESTART takes arbitrary 
parameters which are passed down to the restart.  A handler may use 
this to pass the condition object to the restart.

> The restart may of course do anything --- including getting rid of the
> other conditions on the debug stack, so I'm not sure if this is a
> valid notion in general.

A restart gets rid of a condition by performing a dynamic, non-local 
control transfer to the point where execution is going to resume. (If 
you're using the RESTART-CASE macro, this control transfer takes place 
before the given case is entered; the actual restart is over and done 
with by that point and the condition is handled).
From: Kaz Kylheku
Subject: Re: 2 Comments regarding restarts in the CL Condition system
Date: 
Message-ID: <1169948772.512209.92920@q2g2000cwa.googlegroups.com>
On Jan 27, 4:18 pm, Madhu <·······@meer.net> wrote:
> * "Kaz Kylheku" <························@k78g2000cwa.XXXXXX> :
>
> | Strictly speaking, a restart has nothing to do with conditions. You
> | can invoke restarts in the absence of any condition handling.
>
> Understood. But I'm talking of the case when restarts are used to
> handle condittions. Think restarts in the debugger.  This situation
> cannot be encountered at all without a condition being
> signalled.

INVOKE-DEBUGGER

:)


> Again, understood.  However, if you are in the debugger, you (as a
> user) cannot pass the condition to INVOKE-RESTART.  This has to be
> coded up explicitly, in a different room, behind the scenes.

If you can evaluate a INVOKE-RESTART expression, and you have a way to 
get to that condition, you should be able to do it.

To capture the condition, you could have your own handler installed 
which stores it in some special variable and then declines to handle 
it.

Also, *DEBUGGER-HOOK* may be useful to you.