From: Nathan Baum
Subject: (warn) isn't doing what I expect it to
Date: 
Message-ID: <df00lg$gr3$1@newsg1.svr.pol.co.uk>
I'm expecting

   (handler-case
       (warn "foo")
     (warning (c) (muffle-warning c)))

to produce no output, successfully. Instead it produces

   *** - INVOKE-RESTART: No restart named MUFFLE-WARNING is visible.

CLHS says WARN establishes a MUFFLE-WARNING restart. What am I doing wrong?

From: Wade Humeniuk
Subject: Re: (warn) isn't doing what I expect it to
Date: 
Message-ID: <kILQe.211354$9A2.49579@edtnps89>
Nathan Baum wrote:
> I'm expecting
> 
>   (handler-case
>       (warn "foo")
>     (warning (c) (muffle-warning c)))
> 
> to produce no output, successfully. Instead it produces
> 
>   *** - INVOKE-RESTART: No restart named MUFFLE-WARNING is visible.
> 
> CLHS says WARN establishes a MUFFLE-WARNING restart. What am I doing wrong?

By the time the warning handler is called the stack is already unwound.
(There is no muffle-warning restart).
You need to use handler-bind instead.  With handler-bind the handler
is called without unwinding the current stack.

CL-USER 1 > (handler-bind
                 ((warning (lambda (c)
                             (muffle-warning c))))
               (warn "foo"))
NIL

CL-USER 2 >

Wade
From: Nathan Baum
Subject: Re: (warn) isn't doing what I expect it to
Date: 
Message-ID: <df0159$chu$2@newsg2.svr.pol.co.uk>
Wade Humeniuk wrote:
> Nathan Baum wrote:
> 
>> I'm expecting
>>
>>   (handler-case
>>       (warn "foo")
>>     (warning (c) (muffle-warning c)))
>>
>> to produce no output, successfully. Instead it produces
>>
>>   *** - INVOKE-RESTART: No restart named MUFFLE-WARNING is visible.
>>
>> CLHS says WARN establishes a MUFFLE-WARNING restart. What am I doing 
>> wrong?
> 
> 
> By the time the warning handler is called the stack is already unwound.
> (There is no muffle-warning restart).
> You need to use handler-bind instead.  With handler-bind the handler
> is called without unwinding the current stack.
> 
> CL-USER 1 > (handler-bind
>                 ((warning (lambda (c)
>                             (muffle-warning c))))
>               (warn "foo"))
> NIL
> 

That's just great, thanks. :)
From: Nathan Baum
Subject: Re: (warn) isn't doing what I expect it to
Date: 
Message-ID: <df012t$chu$1@newsg2.svr.pol.co.uk>
Nathan Baum wrote:
> I'm expecting
> 
>   (handler-case
>       (warn "foo")
>     (warning (c) (muffle-warning c)))
> 
> to produce no output, successfully. Instead it produces
> 
>   *** - INVOKE-RESTART: No restart named MUFFLE-WARNING is visible.
> 
> CLHS says WARN establishes a MUFFLE-WARNING restart. What am I doing wrong?

So HANDLER-CASE unwinds the dynamic environments before executing its 
forms. Most unexpected. It works if I use HANDLER-BIND.

   (handler-bind
       ((warning #'(lambda (c) (muffle-warning c))))
     (warn "foo"))

I think that's a bit ugly, though. Is there a common idiom for what I 
want to do, or should I go ahead and roll my own macro?
From: Wade Humeniuk
Subject: Re: (warn) isn't doing what I expect it to
Date: 
Message-ID: <ESLQe.211481$9A2.195314@edtnps89>
Nathan Baum wrote:

> So HANDLER-CASE unwinds the dynamic environments before executing its 
> forms. Most unexpected. It works if I use HANDLER-BIND.
> 
>   (handler-bind
>       ((warning #'(lambda (c) (muffle-warning c))))
>     (warn "foo"))
> 
> I think that's a bit ugly, though. Is there a common idiom for what I 
> want to do, or should I go ahead and roll my own macro?

There is an example of doing just what you want in the section
on the MUFFLE-WARNING restart,

See

http://www.lispworks.com/documentation/HyperSpec/Body/r_muffle.htm

Wade
From: Kent M Pitman
Subject: Re: (warn) isn't doing what I expect it to
Date: 
Message-ID: <u7je4id6v.fsf@nhplace.com>
Nathan Baum <···········@btinternet.com> writes:

> Nathan Baum wrote:
> > I'm expecting
> >   (handler-case
> >       (warn "foo")
> >     (warning (c) (muffle-warning c)))
> > to produce no output, successfully. Instead it produces
> >   *** - INVOKE-RESTART: No restart named MUFFLE-WARNING is visible.
> > CLHS says WARN establishes a MUFFLE-WARNING restart. What am I doing
> > wrong?
> 
> So HANDLER-CASE unwinds the dynamic environments before executing its
> forms. Most unexpected.

Right.  And it's the normal semantics for Java and C++.
That is to say, it is often useless in doing serious error handling.
Both of those languages lack the ability to handle the error in its
original context, which is the time when interesting restarts are
possible.  In fact, they have no restart facility at all.  Just a 
catch-like facility.  Because once you've thrown out of the error, that
nuance of how to proceed is far less relevant.

> It works if I use HANDLER-BIND.
> 
>    (handler-bind
>        ((warning #'(lambda (c) (muffle-warning c))))
>      (warn "foo"))
> 
> I think that's a bit ugly, though. Is there a common idiom for what I
> want to do, or should I go ahead and roll my own macro?

If all you're going to write is that, use
 (handler-bind ((warning #'muffle-warning))
   (warn "foo"))
Some people prefer to protect themselves from non-conforming implementations
and might write:
 (handler-bind ((warning #'(lambda (c)
                             (let ((r (find-restart 'muffle-warning c)))
                               (when r (invoke-restart r))))))
   (warn "foo"))
Though there's no reason  you can't write
 (defun muffle-warnings-if-possible (warning)
   (let ((restart (find-restart 'muffle-warning warning)))
     (when restart (invoke-restart appropriate-restart))))
and then something like
 (defmacro muffling-warnings (&body forms)
   `(handler-bind ((warning #'muffle-warnings-if-possible))
      ,@forms))
so that you can just do
 (muffling-warnings
   (warn "foo"))
From: Edi Weitz
Subject: Re: (warn) isn't doing what I expect it to
Date: 
Message-ID: <u3bosl7an.fsf@agharta.de>
On Mon, 29 Aug 2005 23:13:44 +0100, Nathan Baum <···········@btinternet.com> wrote:

> So HANDLER-CASE unwinds the dynamic environments before executing
> its forms. Most unexpected. It works if I use HANDLER-BIND.

Why unexpected?  That exactly is the difference between HANDLER-CASE
and HANDLER-BIND.

>    (handler-bind
>        ((warning #'(lambda (c) (muffle-warning c))))
>      (warn "foo"))
>
> I think that's a bit ugly, though.

I don't think that's ugly.  You can replace the lambda form with
#'MUFFLE-WARNING, though.

Cheers,
Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Nathan Baum
Subject: Re: (warn) isn't doing what I expect it to
Date: 
Message-ID: <df04eq$1pu$1@news6.svr.pol.co.uk>
Edi Weitz wrote:
> On Mon, 29 Aug 2005 23:13:44 +0100, Nathan Baum <···········@btinternet.com> wrote:
> 
> 
>>So HANDLER-CASE unwinds the dynamic environments before executing
>>its forms. Most unexpected. It works if I use HANDLER-BIND.
> 
> 
> Why unexpected?  That exactly is the difference between HANDLER-CASE
> and HANDLER-BIND.

But I didn't expect that to be the difference. ;)

Now I know.

>>   (handler-bind
>>       ((warning #'(lambda (c) (muffle-warning c))))
>>     (warn "foo"))
>>
>>I think that's a bit ugly, though.
> 
> 
> I don't think that's ugly.

That's fine. You don't have to agree with me. :)

> You can replace the lambda form with #'MUFFLE-WARNING, though.

In this instance, yes. My real code isn't only muffling the warning; 
it's displaying it in a nice way first. I just want to stop the 
implementation-defined warning output being produced (but of course I 
don't want to prevent further processing where the warning was signalled).

I'll some kind of macro, perhaps like

   (warning-case
      (do-something)
     (missing-function (c)
       (format t "WARNING: Function ~A not found"
               (missing-function-function c))))

if it turns out I need to do this again.

> 
> Cheers,
> Edi.
> 
From: Kent M Pitman
Subject: Re: (warn) isn't doing what I expect it to
Date: 
Message-ID: <u1x4c9s2j.fsf@nhplace.com>
Nathan Baum <···········@btinternet.com> writes:

> Edi Weitz wrote:
> > On Mon, 29 Aug 2005 23:13:44 +0100, Nathan Baum <···········@btinternet.com> wrote:
> >
> >>So HANDLER-CASE unwinds the dynamic environments before executing
> >>its forms. Most unexpected. It works if I use HANDLER-BIND.
> > Why unexpected?  That exactly is the difference between HANDLER-CASE
> > and HANDLER-BIND.
> 
> But I didn't expect that to be the difference. ;)

Because you read that the effect would be otherwise in some authoritative
place that was wrong?  Or because you just made up an effect that you hoped
it would happen and wishing didn't make it so?  Or because you mis-read what
someone else had written?  I'm always curious what the source of radical
misconceptions is, and especially so in this case since it's an area about
which there is rampant confusion.  I'm not trying to embarrass  you--this
is just random statistics-taking on my part.  Feel free to reply in private
mail if you'd like.

> In this instance, yes. My real code isn't only muffling the warning;
> it's displaying it in a nice way first. I just want to stop the
> implementation-defined warning output being produced (but of course I
> don't want to prevent further processing where the warning was
> signalled).
> 
> I'll some kind of macro, perhaps like
> 
>    (warning-case
>       (do-something)
>      (missing-function (c)
>        (format t "WARNING: Function ~A not found"
>                (missing-function-function c))))
> 
> if it turns out I need to do this again.

Assuming there is a MISSING-FUNCTION warning that is a subclass of
WARNING (and there is none such defined by CL), you should be able
to do:

 (handler-bind (((and warning (not missing-function))
                #'muffle-warning))
   (do-something))

That is, rather than explicitly force output for something that was
going to output anyway, just head off the output for things you don't
want output about...

The idea of writing something to do FORMAT such as you suggest is
wrong for several reasons.

 - You're outputing to *STANDARD-OUTPUT*, which is not where
   warnings are ordinarily meant to go--it gets them mixed up
   in output for programs.

 - You're printing the word "WARNING" onto the stream rather than
   leaving it to the system to use the appropriate notation for the
   particular implementation.

 - You're bypassing the system's natural desire to end your warning
   text with a newline.  You're not required to put a newline into
   a warning or error message, but the system is supposed to supply
   one.

 - You're printing the error message with ~A about the name of a
   function, hiding appropriate escaping that should be done.
   That is, if the function's name is |FOO\\xyz| you're going to
   output FOO\xyz which will confuse people about whether the \
   is part of the name or just an escape for the x that follows.
   If you use ~S instead, the name will output as FOO\\\x\y\z or
   |FOO\\xyz| or FOO\\|xyz| any of which may look ugly, but are
   parseable by Lisp.

 - You're writing code that does (format ...) in order to keep code
   from executing that intends to do (format ...), which is just
   repeated effort.

You might want to read the section on the condition system in ANSI CL
(e.g., via CLHS):
 http://www.lispworks.com/documentation/HyperSpec/Body/09_a.htm
or CLTL2 [which is slightly out-of-date and therefore wrong in a few
technical details but has a more introductory-style presentation you
might find friendly to get started]
 http://cltl2.lisp.se/cltl/clm/node312.html#SECTION003300000000000000000 
and/or you might want to read my two papers on conditions
 http://www.nhplace.com/kent/Papers/Exceptional-Situations-1990.html
 http://www.nhplace.com/kent/Papers/Condition-Handling-2001.html
[These two papers cover different issues, so it's worth reading both.]
From: Nathan Baum
Subject: Re: (warn) isn't doing what I expect it to
Date: 
Message-ID: <df0d3d$toi$1@newsg3.svr.pol.co.uk>
Kent M Pitman wrote:
> Nathan Baum <···········@btinternet.com> writes:
> 
> 
>>Edi Weitz wrote:
>>
>>>On Mon, 29 Aug 2005 23:13:44 +0100, Nathan Baum <···········@btinternet.com> wrote:
>>>
>>>
>>>>So HANDLER-CASE unwinds the dynamic environments before executing
>>>>its forms. Most unexpected. It works if I use HANDLER-BIND.
>>>
>>>Why unexpected?  That exactly is the difference between HANDLER-CASE
>>>and HANDLER-BIND.
>>
>>But I didn't expect that to be the difference. ;)
> 
> Because you read that the effect would be otherwise in some authoritative
> place that was wrong?  Or because you just made up an effect that you hoped
> it would happen and wishing didn't make it so?  Or because you mis-read what
> someone else had written?  I'm always curious what the source of radical
> misconceptions is, and especially so in this case since it's an area about
> which there is rampant confusion.  I'm not trying to embarrass  you--this
> is just random statistics-taking on my part.  Feel free to reply in private
> mail if you'd like.

The closest option you presented was "I just made up an effect that you 
hoped it would happen and wishing didn't make it so."

But it does rather misrepresent things. I didn't just "make up" an 
effect. I expected it to have the same effect as HANDER-BIND except for 
the differences that I already knew it had: its syntax, and inhibiting 
further propogation of the signal.

I didn't expect it to unwind the dynamic state before evaluating the 
handler, because I thought I had already fully grokked the distinction.

> Assuming there is a MISSING-FUNCTION warning that is a subclass of
> WARNING (and there is none such defined by CL), you should be able
> to do:
> 
>  (handler-bind (((and warning (not missing-function))
>                 #'muffle-warning))
>    (do-something))
> 
> That is, rather than explicitly force output for something that was
> going to output anyway, just head off the output for things you don't
> want output about...

As I made clear, I _don't_ want the implementation dependent warning 
output. MISSING-FUNCTION is domain-specific condition which I wish to 
display and otherwise respond to in a domain-specific manner.

I want warnings 'from Lisp' to pass through as normal. (Of course the 
cost I originally posted didn't do that, but that was just a 
simplification to illustrate the problem I was having.)

> The idea of writing something to do FORMAT such as you suggest is
> wrong for several reasons.
> 
>  - You're outputing to *STANDARD-OUTPUT*, which is not where
>    warnings are ordinarily meant to go--it gets them mixed up
>    in output for programs.

Not a problem for this instance. The program is an interactive evaluator 
for a non-Lispy language, and I _want_ the warnings to be mixed up in 
output. On the other hand, I want warnings 'from Lisp' to go elsewhere, 
possibly a log.

>  - You're printing the word "WARNING" onto the stream rather than
>    leaving it to the system to use the appropriate notation for the
>    particular implementation.

As noted above, the implementation dependent notation isn't appropriate.

>  - You're bypassing the system's natural desire to end your warning
>    text with a newline.  You're not required to put a newline into
>    a warning or error message, but the system is supposed to supply
>    one.

In the real code, the newline is provided elsewhere. It turned out that 
way because CLISP doesn't put a newline after a warning:

   (progn (warn "foo")
          (princ "bar"))

I don't feel the need to change things, since putting a newline in there 
messes up the display, and removing it from where it is displayed at the 
moment means that normal Lisp warnings (which I'm not yet redirecting to 
a log) will be messed up when using CLISP.

>  - You're printing the error message with ~A about the name of a
>    function, hiding appropriate escaping that should be done.
>    That is, if the function's name is |FOO\\xyz| you're going to
>    output FOO\xyz which will confuse people about whether the \
>    is part of the name or just an escape for the x that follows.
>    If you use ~S instead, the name will output as FOO\\\x\y\z or
>    |FOO\\xyz| or FOO\\|xyz| any of which may look ugly, but are
>    parseable by Lisp.

The function in question isn't a Lisp function, and doesn't follow 
Lisp's rules for symbol syntax. The accessor should probably be 
MISSING-FUNCTION-NAME, since it's a string (at the moment, I haven't 
made these conditions; I'm just using simple conditions).

The function named "|FOO\\xyz|" would genuinely be named "|FOO\\xyz|".

>  - You're writing code that does (format ...) in order to keep code
>    from executing that intends to do (format ...), which is just
>    repeated effort.

I'm writing code that does (format <known arguments>) in order to keep 
code from executing that indends to do (format <implementation dependent 
arguments>).

>  http://www.nhplace.com/kent/Papers/Exceptional-Situations-1990.html
>  http://www.nhplace.com/kent/Papers/Condition-Handling-2001.html
> [These two papers cover different issues, so it's worth reading both.]

Good stuff, thanks.
From: Pascal Bourguignon
Subject: Re: (warn) isn't doing what I expect it to
Date: 
Message-ID: <87u0h89jin.fsf@thalassa.informatimago.com>
Nathan Baum <···········@btinternet.com> writes:
> In the real code, the newline is provided elsewhere. It turned out
> that way because CLISP doesn't put a newline after a warning:
>
>    (progn (warn "foo")
>           (princ "bar"))
>
> I don't feel the need to change things, since putting a newline in
> there messes up the display, and removing it from where it is
> displayed at the moment means that normal Lisp warnings (which I'm not
> yet redirecting to a log) will be messed up when using CLISP.

The point is that lisp is old enough to be born at a time when
newlines were inserted _before_ the lines.  You needed to move to a
new-line to be able to print the current line or punch the current
card.

Note that even on a video terminal, it might be useful to use the
newline before convention, since it gives you one more line on the
screen.  With the newline after, you always get the last like blank
(not that matter much in a 80x60 emacs window ;-).

If you want to follow unix convention, you need to make intensive use
of ~&: (format t "~&bar~%") instead of (princ "bar") to interact
nicely with "older" lisp code.

-- 
"Specifications are for the weak and timid!"
From: Kent M Pitman
Subject: Re: (warn) isn't doing what I expect it to
Date: 
Message-ID: <ud5nveg9a.fsf@nhplace.com>
Pascal Bourguignon <····@mouse-potato.com> writes:

> Nathan Baum <···········@btinternet.com> writes:
> > In the real code, the newline is provided elsewhere. It turned out
> > that way because CLISP doesn't put a newline after a warning:
> >
> >    (progn (warn "foo")
> >           (princ "bar"))
> >
> > I don't feel the need to change things, since putting a newline in
> > there messes up the display, and removing it from where it is
> > displayed at the moment means that normal Lisp warnings (which I'm not
> > yet redirecting to a log) will be messed up when using CLISP.
> 
> The point is that lisp is old enough to be born at a time when
> newlines were inserted _before_ the lines.  You needed to move to a
> new-line to be able to print the current line or punch the current
> card.

Actually, the effect is not just that.  There's actually something that was
a hugely more modern effect that has been left by the wayside as something
I personally consider a dinosaurlike convention won out over what I think
of as more progressive years ago... that is,

On the Lisp Machine, the parser was engaged with the rubout handler such
that you didn't have to press RETURN at the end of a line.  When you typed
the last paren, it knew you were done and it activated immediately.  As a
consequence, you were not on a new line.

Many people like me who come from LispM days always protect our 
output by doing
(format t "~&...~%")
to say "make sure the previous I/O cleaned up, and make sure we don't
leave ourselves mid-line either."  This is not a throwback to when cards
or line printers hadn't advanced, this is an accomodation to "dumb"
command processors that can't tell when you're done typing your command
except by you pressing an additional character not related to the command. :)

So it's just a point-of-view thing, I guess.  Certainly there are more people
in the world who don't think like I do on this point than people who do,
so I won't argue my position is a majority opinion.  But hearing it compared
to punched cards was a bit much...

The Lisp Machine managed rubout handling without having to know what parser
was active, and still managed to win, using an algorithm described in my
Lisp Pointer paper "Ambitious Evaluation" at
 http://www.nhplace.com/kent/PS/Ambitious.html
 
> Note that even on a video terminal, it might be useful to use the
> newline before convention, since it gives you one more line on the
> screen.  With the newline after, you always get the last like blank
> (not that matter much in a 80x60 emacs window ;-).

There's that as well, but the issue isn't just display, it's activation.
 
Additionally, there were some systems where you pressed Enter (a key
distinct from Return or Linefeed) and this meant not to add a newline
character but to activate immediately, submitting what had been typed
but not any termination key.  This again had the issue that it left the
output in an undefined state.

So, for portability, since some command processors took
 <prompt> <command>[output starts here]
and some took
 <prompt> <command><return>
 [output starts here]
the use of ~& was essential to getting portable behavior.  I still 
use it for this reason, always wishing in vain that the world would
catch back up to the cool style of the Lisp Machine rubout handling.

> If you want to follow unix convention, you need to make intensive use
> of ~&: (format t "~&bar~%") instead of (princ "bar") to interact
> nicely with "older" lisp code.

I agree.  Except I'd use the word "newer". :)

Ain't point of view grand?
From: Sam Steingold
Subject: Re: newline conventions
Date: 
Message-ID: <uwtm3ftvj.fsf_-_@gnu.org>
> * Kent M Pitman <······@aucynpr.pbz> [2005-08-30 12:52:43 +0000]:
>
> Many people like me who come from LispM days always protect our 
> output by doing
> (format t "~&...~%")
> to say "make sure the previous I/O cleaned up, and make sure we don't
> leave ourselves mid-line either."

CLISP offers "elastic newline":
<http://clisp.cons.org/impnotes/stream-dict.html#elastic-newline>:

The function (EXT:ELASTIC-NEWLINE [stream]) is like FRESH-LINE but the
other way around: It outputs a conditional newline on stream, which is
canceled if the next output on stream happens to be a newline. More
precisely, (EXT:ELASTIC-NEWLINE [stream]) causes a newline to be output
right before the next character is written on stream, if this character
is not a newline. The newline is also output if the next operation on
the stream is FRESH-LINE, FINISH-OUTPUT, FORCE-OUTPUT or CLOSE.

The functionality of EXT:ELASTIC-NEWLINE is also available through the
FORMAT directive ~..

A technique for avoiding unnecessary blank lines in output is to begin
each chunk of output with a call to FRESH-LINE and to terminate it with
a call to EXT:ELASTIC-NEWLINE.

See
<http://cvs.sourceforge.net/viewcvs.py/*checkout*/clisp/clisp/doc/Newline-Convention.txt>
for rationale.

-- 
Sam Steingold (http://www.podval.org/~sds) running w2k
<http://www.palestinefacts.org/> <http://truepeace.org> <http://www.memri.org/>
<http://ffii.org/> <http://www.dhimmi.com/> <http://www.savegushkatif.org>
If it has syntax, it isn't user friendly.
From: Lars Brinkhoff
Subject: Re: (warn) isn't doing what I expect it to
Date: 
Message-ID: <854q97zhno.fsf@junk.nocrew.org>
Kent M Pitman <······@nhplace.com> writes:
> Additionally, there were some systems where you pressed Enter (a key
> distinct from Return or Linefeed) and this meant not to add a newline
> character but to activate immediately, submitting what had been typed
> but not any termination key.

That's ^D in Unix (except ^D on an empty line will usually be
interpreted as EOF).
From: Kent M Pitman
Subject: Re: (warn) isn't doing what I expect it to
Date: 
Message-ID: <uzmqzd07u.fsf@nhplace.com>
Lars Brinkhoff <·········@nocrew.org> writes:

> Kent M Pitman <······@nhplace.com> writes:
> > Additionally, there were some systems where you pressed Enter (a key
> > distinct from Return or Linefeed) and this meant not to add a newline
> > character but to activate immediately, submitting what had been typed
> > but not any termination key.
> 
> That's ^D in Unix (except ^D on an empty line will usually be
> interpreted as EOF).

And i think some *nix based Lisp systems will close the input stream when
they see a ^D, which isn't so good if you're doing a REPL on that stream.
So it's not quite what I meant.  But it is related.  It's more like ending
your emacs mail message or other recursive edit with control-meta-c.
From: Lars Brinkhoff
Subject: Re: (warn) isn't doing what I expect it to
Date: 
Message-ID: <85zmqzy1ji.fsf@junk.nocrew.org>
Kent M Pitman <······@nhplace.com> writes:
> Lars Brinkhoff <·········@nocrew.org> writes:
> > Kent M Pitman <······@nhplace.com> writes:
> > > Additionally, there were some systems where you pressed Enter (a
> > > key distinct from Return or Linefeed) and this meant not to add
> > > a newline character but to activate immediately, submitting what
> > > had been typed but not any termination key.
> > That's ^D in Unix (except ^D on an empty line will usually be
> > interpreted as EOF).
> And i think some *nix based Lisp systems will close the input stream
> when they see a ^D, which isn't so good if you're doing a REPL on
> that stream.

(This is no longer very Lisp-related, so I'll just write this
additional article.)

They don't see ^D, they see the current input line, without any
terminting character.  (If the line is empty, there will be zero
characters, interpreted as EOF.)  For example, here's a Lisp session
where I used ^D to enter three input lines:

    This is SBCL [...]
    * 42
    42
    * (defun foo () (quit))
    FOO
    * (foo)[Exit]
From: Kent M Pitman
Subject: Re: (warn) isn't doing what I expect it to
Date: 
Message-ID: <uzmqydgaa.fsf@nhplace.com>
Lars Brinkhoff <·········@nocrew.org> writes:

> (This is no longer very Lisp-related, so I'll just write this
> additional article.)

I don't see how a discussion of how Lisp I/O interacts with the computer
is somehow not related to Lisp, so I'll blunder forth.
 
> They don't see ^D, they see the current input line, without any
> terminting character.

Hmm. Interesting to know.

> (If the line is empty, there will be zero characters, interpreted as EOF.)
> For example, here's a Lisp session where I used ^D to enter three input
> lines:
> 
>     This is SBCL [...]
>     * 42
>     42
>     * (defun foo () (quit))
>     FOO
>     * (foo)[Exit]

Btw, for me, on both LispWorks 4.4.5 and Allegro 7.0 on Linux, control-D on
a teletype (i.e., in a REPL in a shell, not in some GUI/IDE thing)
neither echos nor has any apparent effect.  Typed to Emacs with either
of these lisps beneath it by using control-Q to quote it into the
input stream, it just gets ignored, too.  That is (if you assume my
notation ^D below is replaced by an actual control-D (ascii 4), then:
 3^D4 => 34
 (+ 3 ^D 4) => 7

I'm not challenging your claim--just offering information about how other
implementations handle it.  (I assume.  I guess it's possible it's the Linux
or my terminal settings.)
From: Christopher C. Stacy
Subject: keyboard EOF handling [Re: (warn) isn't doing what I expect it to]
Date: 
Message-ID: <uhdd6ptp7.fsf_-_@news.dtpq.com>
Kent M Pitman <······@nhplace.com> writes:
> Lars Brinkhoff <·········@nocrew.org> writes:
> > Kent M Pitman <······@nhplace.com> writes:
> > > Lars Brinkhoff 
> > > > Kent M Pitman
> > > > > Additionally, there were some systems where you pressed Enter
> > > > > (a key distinct from Return or Linefeed) and this meant not to add
> > > > > a newline character but to activate immediately, submitting what
> > > > > had been typed but not any termination key.
> > > > That's ^D in Unix (except ^D on an empty line will usually be
> > > > interpreted as EOF).
> > > And i think some *nix based Lisp systems will close the input stream
> > > when they see a ^D, which isn't so good if you're doing a REPL on
> > > that stream.
> > They don't see ^D, they see the current input line,
> > without any terminting character.  (If the line is empty,
> > there will be zero characters, interpreted as EOF.)
> 
> Btw, for me, on both LispWorks 4.4.5 and Allegro 7.0 on Linux,
> control-D on a teletype (i.e., in a REPL in a shell, not in some
> GUI/IDE thing) neither echos nor has any apparent effect.  
>
> Typed to Emacs with either of these lisps beneath it by using
> control-Q to quote it into the input stream, it just gets ignored,
> too.  That is (if you assume my notation ^D below is replaced by an
> actual control-D (ascii 4), then: 3^D4 => 34 (+ 3 ^D 4) => 7
> 
> I'm not challenging your claim--just offering information about how
> other implementations handle it.  (I assume.  I guess it's possible
> it's the Linux or my terminal settings.)

It is the tty driver on Unix that interprets special characters
such as ^D (to set the EOF flag on the input stream, rather than
passing it as input); it does this according to modes that have 
been set on the device.  It only does the EOF effect when 
the ICANON flag is set.  (You can change which character 
will be the EOF command, by the way.)

Programs that need to read special characters use the tcsetattr()
function to turn off ICANON.   Programs like Emacs also turn off
the ISIG bit, which normally causes interrupt signals to be sent
to the program when you type characters such as ^Z and ^C, since
Emacs doesn't consider those characters to be anything special.

When Emacs opens a pseudo-terminal for an inferior shell
there is undoubtedly some frobulation with the control bits.
Emacs creates and prepares the ptty that it will pass
to the inferior program.  Emacs disables echo, turns off the
ICANON flag and some others, and frobs signal characters, 
up/down-case conversion (from the days when ttys were TTYs), 
tabs, NL->CR mapping, 8th bit handling, line and character
rubout handling, etc.

The command [c-c c-D] will signal EOF on inferiors
with using the function process-send-eof.  
If the target is a pipe, this sends a ^D down the pipe.
If the target is a pty, it closes the pty.

(Yeah, that's more than I wanted to know, too,
but I hadn't read any C code all week, so...)

By the way, the terminal driver and job control features 
of Unix are relatively new.  It used to be that you could 
only run one program at a time.  The reason that you can
type ^Z and interrupt a job and start another one, is a
feature copied from ITS (which had it for decades prior).
A guy from MIT's Project MAC was visiting out at Berkeley 
and put that stuff in.  ^Z was recognized by the ITS 
terminal driver (for ASCII terminals) as being the 
interrupt character.  On the ITS Knight TV keyboards, 
there was a dedicated interupt key ("CALL") instead of ^Z.

The Lisp Machine, of course, had a key labeled ABORT.
It also had a key labeled END.  The keyboard was driven
by an asynchronous process which read characters from
the hardware, and processed special ones -- for example, 
by arranging through the scheduler to deliver an SI:ABORT
condition to the appropriate process.  

(I don't really remember exactly how this worked in detail,
and am going to gloss over it a little bit...)

I think the INTERACTIVE-STREAM methods were also involved
in intercepting special characters (or some of them, anyway)
and could control which characters would be intercepted.
The BREAK or SUSPEND key (depending on which keyboard
you had), and the bucky (control/meta) versions of these
characters were also known to the interception protocol.

But the END key, not being an interrupt character, was handled
at a different level -- it was never specially intercepted.
END was just an ordinary character processed by the application's
stream's methods.  END was just an activation character (like the
RETURN key), known to programs like the rubout handler used in
the "Listener" (interactive REP loop).  Whether END or any other
character would normally be seen by the user of stream depended
only on the semantics of the stream.

These interactive streams that I am talking about are 
also what implements the fancy rubout handling that 
Kent was talking about.

The analogous pieces on Unix would be an interactive streams
library (something like "readline" I guess) that most programs 
would use, which could handle a ^D character, versus the 
kernel's tty driver intercepting that character (depending
on the tty object's flags).

On the gripping hand, another specially intercepted character 
was the FUNCTION key.  I don't think you could override it.
The sequence [FUNCTION END] would insert an out-of-band
EOF mark into the IO buffer of the input stream currently
associated with the console.  (This is like ^D on Unix.)

Other FUNCTION key sequences were for things like clearing
buffered typeahead, arresting (not aborting) the processes, 
frobbing various standard IO flags in the stream currently
using the console (such as automatic "more" processing and
window attention notifications) and other various window
system operations (such as rotating windows, clearing or
smashing window system locks in case of horrible bugs).
These functions were run in the system's Keyboard
handler process.

Another intercepted character that you could not override 
was the SELECT key; it also read another character to
decide what to do.  Its general purpose was launching
programs ("activities") and switching focus between them
(sort of like the START menu and alt-TAB in MS Windows).

You could add your own functions to the FUNCTION and
SELECT key dispatch tables, and you could make your
handler spin off another process to run an arbitrary
application.

(tv:add-function-key #\c-Page #'com-clear-output-history
                     "Clear the output history of the selected window.")

Some other random FUNCTION commands were: display 
a list of logged-in users on other Lisp Machines
and their locations (aka "Finger"), also useful
for locating idle or free machines; buzz open the
lobby door on your floor; summon the annoyingly slow
elevator to your floor so that you would not have to
stand around waiting for it in the lobby; displaying 
a memory usage indicator ("GC Thermometer"); putting
a news ticker into the system wholine; or playing audio
clips of the HAL 9000 and then shutting down the machine.

Here's an example from my login init file of frobbing
some keys in the TELNET program.  (Apparently the program 
was not properly modularized for this purpose and I didn't
bother to fix that; it should have had a handler method that
would let me map different keys for different flavors of
remote hosts.)  Anyway, you can see from the #\Abort that 
the TELNET program must have used the interupt character
interception protocol to have the Keyboard driver process lay off.

 (setf (aref telnet:*telnet-keys* (char-code #\End)) (ascii-code #\))         ;c-D
 (setf (aref telnet:*telnet-keys* (char-code #\Clear-input)) (ascii-code #\)) ;c-U
 (setf (aref telnet:*telnet-keys* (char-code #\Help)) (ascii-code #\�))      ;c-H
 (setf (aref telnet:*telnet-keys* (char-code #\Suspend)) (ascii-code #\))     ;c-Z
 (setf (aref telnet:*telnet-keys* (char-code #\Abort)) (ascii-code #\))

There was also Left-control-Right-control-Left-meta-Right-meta-Rubout,
which would reboot the machine.  Also, double-bucky-Return to warm boot.
These characters were never seen by Lisp at any level.  They were handled
by the front-end processor.  I don't remember the original machine having
any FEP - I think the keyboard circuitry actually drove the RESET line
on the machine!  On the 3600, the FEP was a 68000 programmed in a static
language of Lisp syntax (cross-compiled, with Lisp macros).   The FEP
didn't do much during normal operation -- it implemented the bootloader.
Both Lisp and the FEP had code to access a low-level disk file system,
which are a lot liked what we call "disk partitions" on systems today.
But it was much more flexible than "partitions", and it was a full-up
user-accessible file system.  For example, if you found yourself in a
dire lurch where your normal file system (contained within a file on
this FEPFS) was broken or something, and you didn't have a working
network, you could write your Emacs buffers out to FEPFS files.
(And if you think having a 68000 and all this is overkill, yeah,
and a Z80 was used as the controller in the keyboard/CRT console head.
It's main job was to implement the brightness knob.)  On the Ivory chip, 
the "FEP" was just a mode that the machine could go into for booting.

Lars Brinkhoff <·········@nocrew.org> writes:
> (This is no longer very Lisp-related, so I'll 
> just write this additional article.)

It didn't seem too far off-topic or non-Lisp to me, 
but then I like to pretend I'm Richard Burke or something.

We should have changed the subject line a while back.
I'll change it here so that people might look back upthread
and find Kent's description of the nifty rubout handler.
From: Robert Uhl
Subject: Re: keyboard EOF handling [Re: (warn) isn't doing what I expect it to]
Date: 
Message-ID: <m3d5nuvz4f.fsf@4dv.net>
······@news.dtpq.com (Christopher C. Stacy) writes:
>
> It is the tty driver on Unix that interprets special characters such
> as ^D (to set the EOF flag on the input stream, rather than passing it
> as input); it does this according to modes that have been set on the
> device.  It only does the EOF effect when the ICANON flag is set.
> (You can change which character will be the EOF command, by the way.)

Yup; for fun run stty eof l or stty eof c...

-- 
Robert Uhl <http://public.xdi.org/=ruhl>
Mailserver lockup.
Error message boggles mind.
Oh well.  Beer is cold.
        --Jason Wright
From: Barry Margolin
Subject: Re: keyboard EOF handling [Re: (warn) isn't doing what I expect it to]
Date: 
Message-ID: <barmar-4E8606.19164931082005@comcast.dca.giganews.com>
In article <················@news.dtpq.com>,
 ······@news.dtpq.com (Christopher C. Stacy) wrote:

> The command [c-c c-D] will signal EOF on inferiors
> with using the function process-send-eof.  
> If the target is a pipe, this sends a ^D down the pipe.
> If the target is a pty, it closes the pty.

I think you got that backward.  You close a pipe, and send ^D down a pty.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: Christopher C. Stacy
Subject: Re: keyboard EOF handling [Re: (warn) isn't doing what I expect it to]
Date: 
Message-ID: <ubr3dgzu2.fsf@news.dtpq.com>
Barry Margolin <······@alum.mit.edu> writes:

> In article <················@news.dtpq.com>,
>  ······@news.dtpq.com (Christopher C. Stacy) wrote:
> 
> > The command [c-c c-D] will signal EOF on inferiors
> > with using the function process-send-eof.  
> > If the target is a pipe, this sends a ^D down the pipe.
> > If the target is a pty, it closes the pty.
> 
> I think you got that backward.  You close a pipe, and send ^D down a pty.

You are correct.

  if (!NILP (XPROCESS (proc)->pty_flag))
    send_process (proc, "\004", 1, Qnil);

I missed the "!" in the double-negative.
From: lin8080
Subject: Re: keyboard EOF handling [Re: (warn) isn't doing what I expect it to]
Date: 
Message-ID: <43188704.D0DDDCAA@freenet.de>
"Christopher C. Stacy" schrieb:

Hey.

Just another view. 
I use Windows, starting CLisp is max a 50 line Dosbox with the very old
command line. (newline takes place in the middle of a word). Loading
something beginns with path names (a disaster for some newbies). 
But still, I do not install emacs on my box. Sorry, but do you think it
is clever to install 25MB software to handle 5MB Interpreter and double
the learncurve with that act? Hm. It seems, you want a lisp like emacs2. 

stefan
From: Christopher C. Stacy
Subject: Re: keyboard EOF handling [Re: (warn) isn't doing what I expect it to]
Date: 
Message-ID: <uu0h3caua.fsf@news.dtpq.com>
lin8080 <·······@freenet.de> writes:

> "Christopher C. Stacy" schrieb:
> 
> Hey.
> 
> Just another view. 
> I use Windows, starting CLisp is max a 50 line Dosbox with the very old
> command line. (newline takes place in the middle of a word). Loading
> something beginns with path names (a disaster for some newbies). 
> But still, I do not install emacs on my box. Sorry, but do you think it
> is clever to install 25MB software to handle 5MB Interpreter and double
> the learncurve with that act? Hm. It seems, you want a lisp like emacs2. 

I have no idea what this is in response to (especially what 
it has to do with EOF handling on Unix, or the WARN function).

But in general, yes, I think people who install Emacs
are generally being clever about something.
But why do you care what my opinion there?
From: http://public.xdi.org/=pf
Subject: Re: (warn) isn't doing what I expect it to
Date: 
Message-ID: <m23boqps31.fsf@mycroft.actrix.gen.nz>
On Wed, 31 Aug 2005 01:49:41 GMT, Kent M Pitman wrote:

>> (If the line is empty, there will be zero characters, interpreted as EOF.)
>> For example, here's a Lisp session where I used ^D to enter three input
>> lines:
>> 
>> This is SBCL [...]
>> * 42
>> 42
>> * (defun foo () (quit))
>> FOO
>> * (foo)[Exit]

> Btw, for me, on both LispWorks 4.4.5 and Allegro 7.0 on Linux, control-D on
> a teletype (i.e., in a REPL in a shell, not in some GUI/IDE thing)
> neither echos nor has any apparent effect.  Typed to Emacs with either
> of these lisps beneath it by using control-Q to quote it into the
> input stream, it just gets ignored, too.  That is (if you assume my

Typing it into Emacs is different.  When you type it into a shell, the
terminal driver intercepts it before it gets passed through to the
program underneath and does something else with it (or may do...you
can change it with `stty', make some other key, or no key at all, have
that functionality; whatever).  But Emacs will just pass the character
through to Lisp (which I expect treats it as whitespace)

Typing it on a non-empty line in a shell just does something like
"force-output" (only in the other direction, of course)

> notation ^D below is replaced by an actual control-D (ascii 4), then:
>  3^D4 => 34
>  (+ 3 ^D 4) => 7

As expected.  But "34 ^D" should give you 34

[Except in CLISP, I guess, since that uses readline...]

-- 
Don't worry about people stealing your ideas. If your ideas are any good,
you'll have to ram them down people's throats.
                                                          -- Howard Aiken
(setq reply-to
  (concatenate 'string "Paul Foley " "<mycroft" '(··@) "actrix.gen.nz>"))
From: Nathan Baum
Subject: Re: (warn) isn't doing what I expect it to
Date: 
Message-ID: <1125606632.462322.21160@g14g2000cwa.googlegroups.com>
Lars Brinkhoff wrote:
> Kent M Pitman <······@nhplace.com> writes:
> > Lars Brinkhoff <·········@nocrew.org> writes:
> > > Kent M Pitman <······@nhplace.com> writes:
> > > > Additionally, there were some systems where you pressed Enter (a
> > > > key distinct from Return or Linefeed) and this meant not to add
> > > > a newline character but to activate immediately, submitting what
> > > > had been typed but not any termination key.
> > > That's ^D in Unix (except ^D on an empty line will usually be
> > > interpreted as EOF).
> > And i think some *nix based Lisp systems will close the input stream
> > when they see a ^D, which isn't so good if you're doing a REPL on
> > that stream.
>
> (This is no longer very Lisp-related, so I'll just write this
> additional article.)
>
> They don't see ^D, they see the current input line, without any
> terminting character.  (If the line is empty, there will be zero
> characters, interpreted as EOF.)  For example, here's a Lisp session
> where I used ^D to enter three input lines:
>
>     This is SBCL [...]
>     * 42
>     42
>     * (defun foo () (quit))
>     FOO
>     * (foo)[Exit]

I must say I wouldn't like that at all.

I _expect_ ^D to be interpreted as an EOF character in any line-based
program. CMUCL irritates me by not allowing me to enter ^D on a fresh
line and just quit.
From: Christophe Rhodes
Subject: Re: (warn) isn't doing what I expect it to
Date: 
Message-ID: <sq7je0cybe.fsf@cam.ac.uk>
"Nathan Baum" <···········@btinternet.com> writes:

> Lars Brinkhoff wrote:
>>     This is SBCL [...]
>>     * 42
>>     42
>>     * (defun foo () (quit))
>>     FOO
>>     * (foo)[Exit]
>
> I must say I wouldn't like that at all.
>
> I _expect_ ^D to be interpreted as an EOF character in any line-based
> program. CMUCL irritates me by not allowing me to enter ^D on a fresh
> line and just quit.

How often have you typed ^D on non-empty lines?  (In _any_ program
that you run in a terminal)

Christophe
From: Rob Warnock
Subject: Re: (warn) isn't doing what I expect it to
Date: 
Message-ID: <MdKdnXj9carSkIXeRVn-sA@speakeasy.net>
Nathan Baum <···········@btinternet.com> wrote:
+---------------
| I _expect_ ^D to be interpreted as an EOF character in any line-based
| program.
+---------------

Then you do not understand how Unix-based terminal drivers work!!
As other have noted, the "EOF" character (^D or otherwise) is
*just* a "push" which completes a blocking "read()", and nothing else.
All of the "EOF" semantics occur because an EOF character typed
on an empty line [and *ONLY* and *empty* line!] causes a "push"
with no characters read yet, and thus "read()" returns zero, and
the Unix/Linux/POSIX convention is that "read()" returning zero
means "EOF".

"Any line-based program" never *sees* the EOF character -- it
*only* sees "read()" returning zero. And if you type "abc^D",
the read returns 3. As it should. As it has since 1971!!

+---------------
| CMUCL irritates me by not allowing me to enter ^D on a fresh
| line and just quit.
+---------------

Ahhh... *That's* a horse of a different color.  ;-}  ;-}
You mean the annoying:

    cmu> Received EOF on *standard-input*, switching to *terminal-io*.
    cmu> 
    Received EOF.
    cmu> 
    Received EOF.
    cmu> 
    Received EOF.
    cmu> 
    ...[and so on, once for every *two* ^D's typed, up to 10 pairs]...

You can fix that with a (SETF *BATCH-MODE* T) in your "~/.cmucl-init"
file [*not* on the command line, though, it'll do other nasty stuff
to you in that case, like exit on any unhandled condition instead of
entering the debugger]. Yes, it still takes *two* ^D's [why? I dunno],
but at least it exits quietly in that case:

    $ cmucl
    ...[chatter]...
    cmu> (setf *batch-mode* t)

    T
    cmu> $ 
	|
	+--- Two ^D's typed here.


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Raymond Toy
Subject: Re: (warn) isn't doing what I expect it to
Date: 
Message-ID: <sxd3boi832y.fsf@rtp.ericsson.se>
>>>>> "Rob" == Rob Warnock <····@rpw3.org> writes:

    Rob> Nathan Baum <···········@btinternet.com> wrote:
    Rob> +---------------
    Rob> | CMUCL irritates me by not allowing me to enter ^D on a fresh
    Rob> | line and just quit.
    Rob> +---------------

    Rob> Ahhh... *That's* a horse of a different color.  ;-}  ;-}
    Rob> You mean the annoying:

[snip]

    Rob> You can fix that with a (SETF *BATCH-MODE* T) in your "~/.cmucl-init"
    Rob> file [*not* on the command line, though, it'll do other nasty stuff
    Rob> to you in that case, like exit on any unhandled condition instead of
    Rob> entering the debugger]. Yes, it still takes *two* ^D's [why? I dunno],
    Rob> but at least it exits quietly in that case:

This seems be be controlled by the constant lisp::eofs-before-quit,
which is 10.  But I see no reason why this can't be a defparameter or
something that the user could set.

But I think just about everyone uses slime or ilisp so this usually
isn't a problem.  For those few occasions where I'm not using slime, I
just type (quit) without even thinking about it.

Ray
From: Rob Warnock
Subject: Re: (warn) isn't doing what I expect it to
Date: 
Message-ID: <dICdnYi3YJR5I4PeRVn-1g@speakeasy.net>
Raymond Toy  <···········@ericsson.com> wrote:
+---------------
| "Rob" == Rob Warnock <····@rpw3.org> writes:
| Rob> You can fix that with a (SETF *BATCH-MODE* T) in your "~/.cmucl-init"
| Rob> file. ...  Yes, it still takes *two* ^D's [why? I dunno],
| Rob> but at least it exits quietly in that case:
| 
| This seems be be controlled by the constant lisp::eofs-before-quit,
| which is 10.  But I see no reason why this can't be a defparameter or
| something that the user could set.
+---------------

Actually, in the case I was talking about, EOFS-BEFORE-QUIT doesn't come
into the picture at all. Look in the code in ".../src/code/lispinit.lisp",
in the function LISP::%TOP-LEVEL, in the COND branch controlled by the
predicate (EQL (INCF NUMBER-OF-EOFS) 1). When *BATCH-MODE* is true, a
single EOF *should* just quit... but for some odd reason it takes two.
Not 0, not 1, not LISP::EOFS-BEFORE-QUIT (10), but exactly 2.

Hmmm... I suspect it has something to do with the implementation
of READ (".../src/code/reader.lisp") and its interaction with the
PROG1 of the READ-PRESERVING-WHITESPACE-INTERNAL call followed by
the READ-CHAR and then the conditional UNREAD-CHAR. Maybe...  ;-}  ;-}

Silly thing to try [of interest only to CMUCL users]: Type the
following to the REPL *without* an ending newline:

	(read-char *standard-input* nil "BOO!")

and see how many EOFs you have to type before it says "BOO!".
In CMUCL-19a [on both Linux & FreeBSD], you have to type *three*!
[With normal Unix TTY semantics, you should only have to type *two*.]
But if you type the same thing followed by a newline, then you only
have to type one EOF. Go figure...


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Edi Weitz
Subject: Re: (warn) isn't doing what I expect it to
Date: 
Message-ID: <u7je4l7g3.fsf@agharta.de>
On Mon, 29 Aug 2005 23:06:35 +0100, Nathan Baum <···········@btinternet.com> wrote:

> I'm expecting
>
>    (handler-case
>        (warn "foo")
>      (warning (c) (muffle-warning c)))
>
> to produce no output, successfully. Instead it produces
>
>    *** - INVOKE-RESTART: No restart named MUFFLE-WARNING is visible.
>
> CLHS says WARN establishes a MUFFLE-WARNING restart. What am I doing
> wrong?

You have to use HANDLER-BIND because otherwise the stack is already
unwound.

  (handler-bind ((warning #'muffle-warning))
    (warn "foo"))

Cheers,
Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Harald Hanche-Olsen
Subject: Re: (warn) isn't doing what I expect it to
Date: 
Message-ID: <pcopsrw8joz.fsf@shuttle.math.ntnu.no>
+ Nathan Baum <···········@btinternet.com>:

| I'm expecting
| 
|    (handler-case
|        (warn "foo")
|      (warning (c) (muffle-warning c)))
| 
| to produce no output, successfully. Instead it produces
| 
|    *** - INVOKE-RESTART: No restart named MUFFLE-WARNING is visible.
| 
| CLHS says WARN establishes a MUFFLE-WARNING restart. What am I doing wrong?

You are using HANDLER-CASE, which unwinds the stack, thereby
discarding the restart, before invoing the handler.

You need to use HANDLER-BIND instead:

(handler-bind
    ((warning #'muffle-warning))
  (warn "foo"))

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Debating gives most of us much more psychological satisfaction
  than thinking does: but it deprives us of whatever chance there is
  of getting closer to the truth.  -- C.P. Snow
From: Harald Hanche-Olsen
Subject: Re: (warn) isn't doing what I expect it to
Date: 
Message-ID: <pcoll2k8j1d.fsf@shuttle.math.ntnu.no>
+ Harald Hanche-Olsen <······@math.ntnu.no>:

| [...] which unwinds the stack

Four independent answers, total discussion so far seven articles.
And all within minutes.  Usenet is just too damn scary sometimes.

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Debating gives most of us much more psychological satisfaction
  than thinking does: but it deprives us of whatever chance there is
  of getting closer to the truth.  -- C.P. Snow