From: Arun Ahuja
Subject: Error Handling
Date: 
Message-ID: <056132df-98d0-4dea-bd1b-a75a56aeefe5@x41g2000hsb.googlegroups.com>
I am a function to process some text and analyze in some fashion.
Every once in a while some function will result in error.  for those,
I'd like to skip that text block, save that in a some variable, and
continue on to the next block.  i've read up on restarts, but I want
this to work for any error.  Any ideas?

From: Richard M Kreuter
Subject: Re: Error Handling
Date: 
Message-ID: <87wsk2oke8.fsf@progn.net>
Arun Ahuja <········@gmail.com> writes:

> I am a function to process some text and analyze in some fashion.
> Every once in a while some function will result in error.  for those,
> I'd like to skip that text block, save that in a some variable, and
> continue on to the next block.  i've read up on restarts, but I want
> this to work for any error.  Any ideas?

Restarts and errors are orthogonal in Common Lisp.  Consider

(defun process-texts (texts)
  (let (bad-texts)
    (dolist (text texts)
      (restart-case (process-one-text text)
        (continue ()
          :report "Skip this text.")
        (collect-it ()
          :report "Collect this text."
          (push text bad-texts))))
    bad-texts))

In this example, PROCESS-TEXTS doesn't know anything about errors;
PROCESS-TEXTS merely offer two ways of proceeding in case an error
occurs during PROCESS-ONE-TEXT; the calling environment can supply a
handler that invokes whichever restart is appropriate.

--
RmK
From: Pascal Costanza
Subject: Re: Error Handling
Date: 
Message-ID: <6d4g40Fq7kaU1@mid.individual.net>
Arun Ahuja wrote:
> I am a function to process some text and analyze in some fashion.
> Every once in a while some function will result in error.  for those,
> I'd like to skip that text block, save that in a some variable, and
> continue on to the next block.  i've read up on restarts, but I want
> this to work for any error.  Any ideas?

(loop with errors
       for block in lists-of-text-blocks
       when (handler-case (process block)
              (error (e)
                (push (cons e block) errors)
                nil))
       collect it into processed-blocks
       finally (return (values processed-blocks errors)))

Untested.


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Arun Ahuja
Subject: Re: Error Handling
Date: 
Message-ID: <c84f22d0-6c32-49f0-98e1-01c2f61a23a1@2g2000hsn.googlegroups.com>
On Jul 3, 12:21 pm, Pascal Costanza <····@p-cos.net> wrote:
> Arun Ahuja wrote:
> > I am a function to process some text and analyze in some fashion.
> > Every once in a while some function will result in error.  for those,
> > I'd like to skip that text block, save that in a some variable, and
> > continue on to the next block.  i've read up on restarts, but I want
> > this to work for any error.  Any ideas?
>
> (loop with errors
>        for block in lists-of-text-blocks
>        when (handler-case (process block)
>               (error (e)
>                 (push (cons e block) errors)
>                 nil))
>        collect it into processed-blocks
>        finally (return (values processed-blocks errors)))
>
> Untested.
>
> Pascal
>
> --
> My website:http://p-cos.net
> Common Lisp Document Repository:http://cdr.eurolisp.org
> Closer to MOP & ContextL:http://common-lisp.net/project/closer/

I am trying to get this to work in a mapcar though.

For example:

(mapcar #'process list-of-textblocks)

would I be able do (mapcar #'(lambda (x) (handler-case... ) (process
x)) list-of-textblocks)
From: Arun Ahuja
Subject: Re: Error Handling
Date: 
Message-ID: <5e2a127c-12a8-41a0-b2f9-3b258d5a616f@e39g2000hsf.googlegroups.com>
On Jul 3, 12:59 pm, Arun Ahuja <········@gmail.com> wrote:
> On Jul 3, 12:21 pm, Pascal Costanza <····@p-cos.net> wrote:
>
>
>
>
>
> > Arun Ahuja wrote:
> > > I am a function to process some text and analyze in some fashion.
> > > Every once in a while some function will result in error.  for those,
> > > I'd like to skip that text block, save that in a some variable, and
> > > continue on to the next block.  i've read up on restarts, but I want
> > > this to work for any error.  Any ideas?
>
> > (loop with errors
> >        for block in lists-of-text-blocks
> >        when (handler-case (process block)
> >               (error (e)
> >                 (push (cons e block) errors)
> >                 nil))
> >        collect it into processed-blocks
> >        finally (return (values processed-blocks errors)))
>
> > Untested.
>
> > Pascal
>
> > --
> > My website:http://p-cos.net
> > Common Lisp Document Repository:http://cdr.eurolisp.org
> > Closer to MOP & ContextL:http://common-lisp.net/project/closer/
>
> I am trying to get this to work in a mapcar though.
>
> For example:
>
> (mapcar #'process list-of-textblocks)
>
> would I be able do (mapcar #'(lambda (x) (handler-case... ) (process
> x)) list-of-textblocks)- Hide quoted text -
>
> - Show quoted text -

I have tried this: which doesn't seem to ignore errors.

(mapcar #'(lambda (x) (handler-case (process x)
                                               (error (e)
                                                 (push (cons e x)
errors)
                                                 nil)))
                         text-list)
From: Pascal Costanza
Subject: Re: Error Handling
Date: 
Message-ID: <6d4ivjFq5lnU1@mid.individual.net>
Arun Ahuja wrote:
> On Jul 3, 12:59 pm, Arun Ahuja <········@gmail.com> wrote:
>> On Jul 3, 12:21 pm, Pascal Costanza <····@p-cos.net> wrote:
>>
>>
>>
>>
>>
>>> Arun Ahuja wrote:
>>>> I am a function to process some text and analyze in some fashion.
>>>> Every once in a while some function will result in error.  for those,
>>>> I'd like to skip that text block, save that in a some variable, and
>>>> continue on to the next block.  i've read up on restarts, but I want
>>>> this to work for any error.  Any ideas?
>>> (loop with errors
>>>        for block in lists-of-text-blocks
>>>        when (handler-case (process block)
>>>               (error (e)
>>>                 (push (cons e block) errors)
>>>                 nil))
>>>        collect it into processed-blocks
>>>        finally (return (values processed-blocks errors)))
>>> Untested.
>>> Pascal
>>> --
>>> My website:http://p-cos.net
>>> Common Lisp Document Repository:http://cdr.eurolisp.org
>>> Closer to MOP & ContextL:http://common-lisp.net/project/closer/
>> I am trying to get this to work in a mapcar though.

Why?

>> For example:
>>
>> (mapcar #'process list-of-textblocks)
>>
>> would I be able do (mapcar #'(lambda (x) (handler-case... ) (process
>> x)) list-of-textblocks)- Hide quoted text -
>>
>> - Show quoted text -
> 
> I have tried this: which doesn't seem to ignore errors.
> 
> (mapcar #'(lambda (x) (handler-case (process x)
>                                                (error (e)
>                                                  (push (cons e x)
> errors)
>                                                  nil)))
>                          text-list)

What do you mean by "doesn't seem to ignore errors"?

Can you show us an interaction in your Lisp listener, so that we can see 
the output of what you try to do?


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Arun Ahuja
Subject: Re: Error Handling
Date: 
Message-ID: <dd7aa877-564e-447f-b6a5-d470316f1318@w7g2000hsa.googlegroups.com>
On Jul 3, 1:09 pm, Pascal Costanza <····@p-cos.net> wrote:
> Arun Ahuja wrote:
> > On Jul 3, 12:59 pm, Arun Ahuja <········@gmail.com> wrote:
> >> On Jul 3, 12:21 pm, Pascal Costanza <····@p-cos.net> wrote:
>
> >>> Arun Ahuja wrote:
> >>>> I am a function to process some text and analyze in some fashion.
> >>>> Every once in a while some function will result in error.  for those,
> >>>> I'd like to skip that text block, save that in a some variable, and
> >>>> continue on to the next block.  i've read up on restarts, but I want
> >>>> this to work for any error.  Any ideas?
> >>> (loop with errors
> >>>        for block in lists-of-text-blocks
> >>>        when (handler-case (process block)
> >>>               (error (e)
> >>>                 (push (cons e block) errors)
> >>>                 nil))
> >>>        collect it into processed-blocks
> >>>        finally (return (values processed-blocks errors)))
> >>> Untested.
> >>> Pascal
> >>> --
> >>> My website:http://p-cos.net
> >>> Common Lisp Document Repository:http://cdr.eurolisp.org
> >>> Closer to MOP & ContextL:http://common-lisp.net/project/closer/
> >> I am trying to get this to work in a mapcar though.
>
> Why?
>
>
>
>
>
> >> For example:
>
> >> (mapcar #'process list-of-textblocks)
>
> >> would I be able do (mapcar #'(lambda (x) (handler-case... ) (process
> >> x)) list-of-textblocks)- Hide quoted text -
>
> >> - Show quoted text -
>
> > I have tried this: which doesn't seem to ignore errors.
>
> > (mapcar #'(lambda (x) (handler-case (process x)
> >                                                (error (e)
> >                                                  (push (cons e x)
> > errors)
> >                                                  nil)))
> >                          text-list)
>
> What do you mean by "doesn't seem to ignore errors"?
>
> Can you show us an interaction in your Lisp listener, so that we can see
> the output of what you try to do?
>
> Pascal
>
> --
> My website:http://p-cos.net
> Common Lisp Document Repository:http://cdr.eurolisp.org
> Closer to MOP & ContextL:http://common-lisp.net/project/closer/- Hide quoted text -
>
> - Show quoted text -- Hide quoted text -
>
> - Show quoted text -

Sorry for the lack of specificity.

I'm not sure what the first 'Why?' is directed at, but to answer the
rest:

What I'd like is the function to run until it hits an error at a
certain block, and then at the error, record the error and not exit
the program but simply continue to the next block
The code I wrote above, gets the error and exits rather then
continuing.  right now, I am just trying this on a toy example trying
to get it work
From: Pascal J. Bourguignon
Subject: Re: Error Handling
Date: 
Message-ID: <87lk0ix14s.fsf@hubble.informatimago.com>
Arun Ahuja <········@gmail.com> writes:

> On Jul 3, 1:09�pm, Pascal Costanza <····@p-cos.net> wrote:
>> Arun Ahuja wrote:
>> > On Jul 3, 12:59 pm, Arun Ahuja <········@gmail.com> wrote:
>> >> On Jul 3, 12:21 pm, Pascal Costanza <····@p-cos.net> wrote:
>> >> I am trying to get this to work in a mapcar though.
>>
>> Why?
>
> I'm not sure what the first 'Why?' is directed at, 

Why are you trying to get this to work in a mapcar though?

Don't you know the eliza program?  You could learn from its
algorithms...

So, why do you want mapcar when you already have a perfectly working
iterative solution (using loop)?


> but to answer the
> rest:
>
> What I'd like is the function to run until it hits an error at a
> certain block, and then at the error, record the error and not exit
> the program but simply continue to the next block
> The code I wrote above, gets the error and exits rather then
> continuing.  

You are lying!  Your code works perfectly as you say you want it to
work:

C/USER[1]> (let ((text-list '("abc" "def" 42 "klm")))
             (flet ((process (x) (string-upcase x)))
               (let ((errors '()))
                 (values (mapcar (lambda (x) (handler-case (process x)
                                               (error (e)
                                                 (push (cons e x) errors)
                                                 nil)))
                                 text-list)
                         errors))))
("ABC" "DEF" NIL "KLM") ;
((#<SIMPLE-TYPE-ERROR #x207D0A76> . 42))


> right now, I am just trying this on a toy example trying
> to get it work

Why don't you show us your toy example?



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

"Specifications are for the weak and timid!"
From: Arun Ahuja
Subject: Re: Error Handling
Date: 
Message-ID: <fac23ed5-85dd-48ce-a70d-f243d90c8059@d1g2000hsg.googlegroups.com>
On Jul 3, 1:40 pm, ····@informatimago.com (Pascal J. Bourguignon)
wrote:
> Arun Ahuja <········@gmail.com> writes:
> > On Jul 3, 1:09 pm, Pascal Costanza <····@p-cos.net> wrote:
> >> Arun Ahuja wrote:
> >> > On Jul 3, 12:59 pm, Arun Ahuja <········@gmail.com> wrote:
> >> >> On Jul 3, 12:21 pm, Pascal Costanza <····@p-cos.net> wrote:
> >> >> I am trying to get this to work in a mapcar though.
>
> >> Why?
>
> > I'm not sure what the first 'Why?' is directed at,
>
> Why are you trying to get this to work in a mapcar though?
>
> Don't you know the eliza program?  You could learn from its
> algorithms...
>
> So, why do you want mapcar when you already have a perfectly working
> iterative solution (using loop)?
>
> > but to answer the
> > rest:
>
> > What I'd like is the function to run until it hits an error at a
> > certain block, and then at the error, record the error and not exit
> > the program but simply continue to the next block
> > The code I wrote above, gets the error and exits rather then
> > continuing.  
>
> You are lying!  Your code works perfectly as you say you want it to
> work:
>
> C/USER[1]> (let ((text-list '("abc" "def" 42 "klm")))
>              (flet ((process (x) (string-upcase x)))
>                (let ((errors '()))
>                  (values (mapcar (lambda (x) (handler-case (process x)
>                                                (error (e)
>                                                  (push (cons e x) errors)
>                                                  nil)))
>                                  text-list)
>                          errors))))
> ("ABC" "DEF" NIL "KLM") ;
> ((#<SIMPLE-TYPE-ERROR #x207D0A76> . 42))
>
> > right now, I am just trying this on a toy example trying
> > to get it work
>
> Why don't you show us your toy example?
>
> --
> __Pascal Bourguignon__                    http://www.informatimago.com/
>
> "Specifications are for the weak and timid!"

Yes, I have seem to have gotten it to work.  This forum takes some
time for the posts to appear, but I posted, and then got it to work,
(it was exiting for a separte reason) and then since my post hadn't
shown up yet, I didn't post a correction.

Thank you for the help.

However, I am interested to hear why you would rather I use loop
rather then mapcar?  Efficiency wise?  I have just personally
preferred mapcar, and it was how the older non-error correcting
function was written.  Also, thank you to the second poster for more
information on restarts
From: Arun Ahuja
Subject: Re: Error Handling
Date: 
Message-ID: <29f0a557-0c4e-49c6-8d7e-2044fbbbdfc2@56g2000hsm.googlegroups.com>
On Jul 3, 2:15 pm, Arun Ahuja <········@gmail.com> wrote:
> On Jul 3, 1:40 pm, ····@informatimago.com (Pascal J. Bourguignon)
> wrote:
>
>
>
>
>
> > Arun Ahuja <········@gmail.com> writes:
> > > On Jul 3, 1:09 pm, Pascal Costanza <····@p-cos.net> wrote:
> > >> Arun Ahuja wrote:
> > >> > On Jul 3, 12:59 pm, Arun Ahuja <········@gmail.com> wrote:
> > >> >> On Jul 3, 12:21 pm, Pascal Costanza <····@p-cos.net> wrote:
> > >> >> I am trying to get this to work in a mapcar though.
>
> > >> Why?
>
> > > I'm not sure what the first 'Why?' is directed at,
>
> > Why are you trying to get this to work in a mapcar though?
>
> > Don't you know the eliza program?  You could learn from its
> > algorithms...
>
> > So, why do you want mapcar when you already have a perfectly working
> > iterative solution (using loop)?
>
> > > but to answer the
> > > rest:
>
> > > What I'd like is the function to run until it hits an error at a
> > > certain block, and then at the error, record the error and not exit
> > > the program but simply continue to the next block
> > > The code I wrote above, gets the error and exits rather then
> > > continuing.  
>
> > You are lying!  Your code works perfectly as you say you want it to
> > work:
>
> > C/USER[1]> (let ((text-list '("abc" "def" 42 "klm")))
> >              (flet ((process (x) (string-upcase x)))
> >                (let ((errors '()))
> >                  (values (mapcar (lambda (x) (handler-case (process x)
> >                                                (error (e)
> >                                                  (push (cons e x) errors)
> >                                                  nil)))
> >                                  text-list)
> >                          errors))))
> > ("ABC" "DEF" NIL "KLM") ;
> > ((#<SIMPLE-TYPE-ERROR #x207D0A76> . 42))
>
> > > right now, I am just trying this on a toy example trying
> > > to get it work
>
> > Why don't you show us your toy example?
>
> > --
> > __Pascal Bourguignon__                    http://www.informatimago.com/
>
> > "Specifications are for the weak and timid!"
>
> Yes, I have seem to have gotten it to work.  This forum takes some
> time for the posts to appear, but I posted, and then got it to work,
> (it was exiting for a separte reason) and then since my post hadn't
> shown up yet, I didn't post a correction.
>
> Thank you for the help.
>
> However, I am interested to hear why you would rather I use loop
> rather then mapcar?  Efficiency wise?  I have just personally
> preferred mapcar, and it was how the older non-error correcting
> function was written.  Also, thank you to the second poster for more
> information on restarts- Hide quoted text -
>
> - Show quoted text -

To revive:

I was wondering what's a way to get more information about the error.
other than just the error code.  For example, when an error occurs the
debuggger gives a an explanation and the expression that went wrong,
however, something like (pprint e) just prints #<simple error @.. > .
Whats a way to access more information.

Also, I'm having trouble printing errors in this form to a file.  I
can't use (write-line error f) or (write-line (write-to-string .. )
what else would work?
From: Kent M Pitman
Subject: Re: Error Handling
Date: 
Message-ID: <uskulqrld.fsf@nhplace.com>
Arun Ahuja <········@gmail.com> writes:

> I was wondering what's a way to get more information about the error.
> other than just the error code.  For example, when an error occurs the
> debuggger gives a an explanation and the expression that went wrong,
> however, something like (pprint e) just prints #<simple error @.. > .
> Whats a way to access more information.

Error objects are, in general, something you should display with 
*PRINT-ESCAPE* being NIL if you want to see an English description.
In practice, that means using FORMAT's ~A or using PRINC.
FORMAT's ~S and the functions PRINT and PRIN1 bind *PRINT-ESCAPE* to T.

Whether PRIN1 and friends show information is dependent on the author
of the error class and whether that author thought that debugging info
of this or that kind was useful.  In fairness, the reason it's not the
default to expose info is that sometimes the information content of an 
error can be internal/ephemeral/circular, and it's not necessarily safe
to show you.

> Also, I'm having trouble printing errors in this form to a file.  I
> can't use (write-line error f) or (write-line (write-to-string .. )
> what else would work?

PRINC-TO-STRING ?  OR WRITE-TO-STRING with a :ESCAPE NIL keyword argument.

I'm curious why you want writeline though. Is that just to make sure there's
a trailing newline?  Recall that error messages may have embedded newlines,
so don't expect that you're going to reliably get a single line of message.

But you might prefer to just use FRESH-LINE after writing the data, rather
than using write-line to write the data.  Doing WRITE-LINE of WRITE-TO-STRING
means consing a string. Whereas doing 
  (PROGN (WRITE ... file-stream) (FRESH-LINE file-stream))
does not [necessarily; one never knows for sure how file-streams are
implemented, but it's their bug if they're inefficient].
From: Vassil Nikolov
Subject: Re: Error Handling
Date: 
Message-ID: <snzej65m742.fsf@luna.vassil.nikolov.name>
On 07 Jul 2008 18:03:58 -0400, Kent M Pitman <······@nhplace.com> said:

| Arun Ahuja <········@gmail.com> writes:
|| I was wondering what's a way to get more information about the error.
|| other than just the error code.  For example, when an error occurs the
|| debuggger gives a an explanation and the expression that went wrong,
|| however, something like (pprint e) just prints #<simple error @.. > .
|| Whats a way to access more information.

| Error objects are, in general, something you should display with 
| *PRINT-ESCAPE* being NIL if you want to see an English description.
| In practice, that means using FORMAT's ~A or using PRINC.
| FORMAT's ~S and the functions PRINT and PRIN1 bind *PRINT-ESCAPE* to T.

| Whether PRIN1 and friends show information is dependent on the author
| of the error class and whether that author thought that debugging info
| of this or that kind was useful.  In fairness, the reason it's not the
| default to expose info is that sometimes the information content of an 
| error can be internal/ephemeral/circular, and it's not necessarily safe
| to show you.

  By the way, when writing out full error details (e.g. in an error
  log), as opposed to "just" producing an error message for an end
  user, I would suggest to do both PRIN1 and PRINC (or their
  equivalents), while ensuring that the condition type of the
  condition is also written (typically, at least one of these two will
  do so, but it's best to make sure---too little detail in an error
  log is certainly worse than too much).

  As an aside, more elaborate error reporting implementations would
  have (at least) two kinds of error messages: one to give to the end
  user, e.g. "The name you entered, 'Foo', is already in use.", and
  another to log for the support personnel, e.g. "The name entered,
  'Foo', is currently used by id '999'."  (Noting that to write out
  the id is not redundant, since by the time a support person is
  looking into this, the name may have even disappeared.)  Then in
  addition to such messages there would be objects (accessible by
  means of reader functions for the condition type) that represent
  relevant state of the system, and so on.

  *        *        *

  Kent, thank you once again for your explanation, some time ago, how
  a condition can be something other than an error condition.

  ---Vassil.


-- 
Peius melius est.  ---Ricardus Gabriel.
From: Kent M Pitman
Subject: Re: Error Handling
Date: 
Message-ID: <ufxqlkkqb.fsf@nhplace.com>
Vassil Nikolov <···············@pobox.com> writes:

>   As an aside, more elaborate error reporting implementations would
>   have (at least) two kinds of error messages: one to give to the end
>   user, e.g. "The name you entered, 'Foo', is already in use.", and
>   another to log for the support personnel, e.g. "The name entered,
>   'Foo', is currently used by id '999'."  (Noting that to write out
>   the id is not redundant, since by the time a support person is
>   looking into this, the name may have even disappeared.)  Then in
>   addition to such messages there would be objects (accessible by
>   means of reader functions for the condition type) that represent
>   relevant state of the system, and so on.

In case it's relevant here: In retrospect, I think the choice to make
the reporting of errors rely on *PRINT-ESCAPE* and not on some
auxiliary mechanism was a mistake.  In part this is because of what
is mentioned above; but also, the thing that errors do with *PRINT-ESCAPE*
is very unlike most other uses of *PRINT-ESCAPE*.

Historically, I perceive that the reason it was done as it was was to
allow easy recycling of ~A in FORMAT.  But probably there should have
been some separate PRINT-HUMAN-READABLE method perhaps on ~H that was
intended not to nest things but to merely print an object in paragraph
form. Then again, there might have been pressuer to make
(PRINT-HUMAN-READABLE '(A B C)) do something goofy like print A, B,
and C, but this would quickly have run into problems even with just
the choice of conjunction, the choice of separator, the choice of
language, etc.  (e.g., a list of conditions [themselves whole
sentences ending in period and not susceptible to having commas placed
after them] or a list of lists [having nesting that might be
arbitrarily deep, again not suitable for commas, which reflect no
nesting] would quickly start to look bad if presented that way).

Better might be just to make it not work at all on abstract
types (such as lists) and only work on "domain types" that have a
well-defined "intentional meaning" for the purpose of human display
(as is the case of conditions).
From: Pascal J. Bourguignon
Subject: Re: Error Handling
Date: 
Message-ID: <87ej64uaio.fsf@hubble.informatimago.com>
Kent M Pitman <······@nhplace.com> writes:

> Vassil Nikolov <···············@pobox.com> writes:
>
>>   As an aside, more elaborate error reporting implementations would
>>   have (at least) two kinds of error messages: one to give to the end
>>   user, e.g. "The name you entered, 'Foo', is already in use.", and
>>   another to log for the support personnel, e.g. "The name entered,
>>   'Foo', is currently used by id '999'."  (Noting that to write out
>>   the id is not redundant, since by the time a support person is
>>   looking into this, the name may have even disappeared.)  Then in
>>   addition to such messages there would be objects (accessible by
>>   means of reader functions for the condition type) that represent
>>   relevant state of the system, and so on.
>
> In case it's relevant here: In retrospect, I think the choice to make
> the reporting of errors rely on *PRINT-ESCAPE* and not on some
> auxiliary mechanism was a mistake.  In part this is because of what
> is mentioned above; but also, the thing that errors do with *PRINT-ESCAPE*
> is very unlike most other uses of *PRINT-ESCAPE*.
>
> Historically, I perceive that the reason it was done as it was was to
> allow easy recycling of ~A in FORMAT.  But probably there should have
> been some separate PRINT-HUMAN-READABLE method perhaps on ~H that was
> intended not to nest things but to merely print an object in paragraph
> form. Then again, there might have been pressuer to make
> (PRINT-HUMAN-READABLE '(A B C)) do something goofy like print A, B,
> and C, but this would quickly have run into problems even with just
> the choice of conjunction, the choice of separator, the choice of
> language, etc.  (e.g., a list of conditions [themselves whole
> sentences ending in period and not susceptible to having commas placed
> after them] or a list of lists [having nesting that might be
> arbitrarily deep, again not suitable for commas, which reflect no
> nesting] would quickly start to look bad if presented that way).

(format t "This is a nested list: ~H~%" list-of-list)

This is a nested list: 
    - car item
    - 
        + caadr item
        + cadadr item
        + caddadr item
        + 
            * caadddadr item
            * cadadddadr item
        + caddddadr item
    - caddr item
    - cadddr item

 
> Better might be just to make it not work at all on abstract
> types (such as lists) and only work on "domain types" that have a
> well-defined "intentional meaning" for the purpose of human display
> (as is the case of conditions).

Yes, but nested lists are easy.

-- 
__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: Vassil Nikolov
Subject: Re: Error Handling
Date: 
Message-ID: <snz63rgmw40.fsf@luna.vassil.nikolov.name>
On Tue, 08 Jul 2008 08:59:11 +0200, ···@informatimago.com (Pascal J. Bourguignon) said:

| Kent M Pitman <······@nhplace.com> writes:
|| ...
|| Then again, there might have been pressure to make
|| (PRINT-HUMAN-READABLE '(A B C)) do something goofy like print A, B,
|| and C, but this would quickly have run into problems even with just
|| the choice of conjunction, the choice of separator, the choice of
|| language, etc.  (e.g., a list of conditions [themselves whole
|| sentences ending in period and not susceptible to having commas placed
|| after them] or a list of lists [having nesting that might be
|| arbitrarily deep, again not suitable for commas, which reflect no
|| nesting] would quickly start to look bad if presented that way).

| (format t "This is a nested list: ~H~%" list-of-list)

| This is a nested list: 
|     - car item
|     - 
|         + caadr item
|         + cadadr item
|         + caddadr item
|         + 
|             * caadddadr item
|             * cadadddadr item
|         + caddddadr item
|     - caddr item
|     - cadddr item

  Let's say, for the sake of argument, that running out of
  leading characters for line items at different levels of nesting (-,
  +, *, then?) is not an issue; and that we are not worried about
  having all-whitespace pseudo-items in the output (to "encode" the
  nesting), or about dotted lists; but how are we going to tackle
  non-cons items which themselves contain newlines (e.g. multi-line
  strings)?  The usual indented textual representation of XML can get
  away with that because of the extra markup, but with that it is not
  really human-readable (humans can read it, but that's only because
  they are rather adaptable...).

  And then all of the above are just technicalities compared to
  dealing with intentionality properly.  For example, the
  human-readable form of

    ((8 3 4) (1 5 9) (6 7 3))

  may be deemed to be

    6 7 2
    1 5 9
    8 3 4

  rather than the nested one.  In other words, are a nested list and a
  tree always the same thing pragmatically?

  ---Vassil.


-- 
Peius melius est.  ---Ricardus Gabriel.
From: Pascal J. Bourguignon
Subject: Re: Error Handling
Date: 
Message-ID: <7c8wwce3yo.fsf@pbourguignon.anevia.com>
Vassil Nikolov <···············@pobox.com> writes:

> On Tue, 08 Jul 2008 08:59:11 +0200, ···@informatimago.com (Pascal J. Bourguignon) said:
>
> | Kent M Pitman <······@nhplace.com> writes:
> || ...
> || Then again, there might have been pressure to make
> || (PRINT-HUMAN-READABLE '(A B C)) do something goofy like print A, B,
> || and C, but this would quickly have run into problems even with just
> || the choice of conjunction, the choice of separator, the choice of
> || language, etc.  (e.g., a list of conditions [themselves whole
> || sentences ending in period and not susceptible to having commas placed
> || after them] or a list of lists [having nesting that might be
> || arbitrarily deep, again not suitable for commas, which reflect no
> || nesting] would quickly start to look bad if presented that way).
>
> | (format t "This is a nested list: ~H~%" list-of-list)
>
> | This is a nested list: 
> |     - car item
> |     - 
> |         + caadr item
> |         + cadadr item
> |         + caddadr item
> |         + 
> |             * caadddadr item
> |             * cadadddadr item
> |         + caddddadr item
> |     - caddr item
> |     - cadddr item
>
>   Let's say, for the sake of argument, that running out of
>   leading characters for line items at different levels of nesting (-,
>   +, *, then?) is not an issue; and that we are not worried about
>   having all-whitespace pseudo-items in the output (to "encode" the
>   nesting), or about dotted lists; but how are we going to tackle
>   non-cons items which themselves contain newlines (e.g. multi-line
>   strings)?  The usual indented textual representation of XML can get
>   away with that because of the extra markup, but with that it is not
>   really human-readable (humans can read it, but that's only because
>   they are rather adaptable...).

That's the point of ~H Human readable format.  It prints data losing
some information, assuming the human reader can infer and recover it,
or in any case,  can deal with the ambiguity. 

(format t "~H" '(a b #(1 2 3) "abc def
ghi klm" y z))

could be printed as:

   - a
   - b 
   - #(1 2 3)
   - abc def
     ghi klm
   - y 
   - z


>   And then all of the above are just technicalities compared to
>   dealing with intentionality properly.  For example, the
>   human-readable form of
>
>     ((8 3 4) (1 5 9) (6 7 3))
>
>   may be deemed to be
>
>     6 7 2
>     1 5 9
>     8 3 4
>
>   rather than the nested one.  In other words, are a nested list and a
>   tree always the same thing pragmatically?

Well, it's ~H, not ~/guess-what-semantics-are-represented-by-this-data/

-- 
__Pascal Bourguignon__
From: Vassil Nikolov
Subject: Re: Error Handling
Date: 
Message-ID: <snzwsjvlx9j.fsf@luna.vassil.nikolov.name>
On Tue, 08 Jul 2008 18:27:27 +0200, ···@informatimago.com (Pascal J. Bourguignon) said:

| Vassil Nikolov <···············@pobox.com> writes:
|| ...
|| And then all of the above are just technicalities compared to
|| dealing with intentionality properly.  For example, the
|| human-readable form of
|| 
|| ((8 3 4) (1 5 9) (6 7 3))

   I missed a typo there in my earlier post; the above was intended to be

     ((6 7 2) (8 3 4) (1 5 9))

|| may be deemed to be
|| 
|| 6 7 2
|| 1 5 9
|| 8 3 4
|| 
|| rather than the nested one.  In other words, are a nested list and a
|| tree always the same thing pragmatically?

| Well, it's ~H, not ~/guess-what-semantics-are-represented-by-this-data/

  No, and it cannot be, which is why I would argue for a different
  facility (or set of facilities) allowing the expression of intent,
  rather than a one-size-fits-all thing.  (If the programmer only
  writes ~H, then there should be a protocol for the ~H writer to
  interrogate the argument, and then we need to spend quite a bit of
  time with this to work it out.)

  ---Vassil.


-- 
Peius melius est.  ---Ricardus Gabriel.
From: Kent M Pitman
Subject: Re: Error Handling
Date: 
Message-ID: <u7ibw2s8q.fsf@nhplace.com>
···@informatimago.com (Pascal J. Bourguignon) writes:

> > Better might be just to make it not work at all on abstract
> > types (such as lists) and only work on "domain types" that have a
> > well-defined "intentional meaning" for the purpose of human display
> > (as is the case of conditions).
> 
> Yes, but nested lists are easy.

I disagree.  What you mean to say is that it's possible to come up with 
something that may seem easy out of context.

The problem is that even just saying something in human language at all
is not easy.  We found this out with y-or-n-p and yes-or-no-p, which cannot
seriously be used by real applications in a portable way.  It can be used
in debugging or by particular implementations where you have inspected what
they do and you agree, but it has the option of using a typescript interface 
or a windowed interface, and in some implementations it makes surprising 
and stylistically confusing interfaces.  The only real way to get this kind 
of thing right is to go at least the route of CLIM with present and accept 
and lots of guidance about interfaces.

Even with the tabbed interface you propose, the ability of the system
to choose on a whim that it was going to use ascii-graphics bullets as
opposed to rendered bullets as opposed to javascript-like active text
would completely change the usability in an unpredictable way.  By contrast,
a detailed worked-out convention for how to structure and merge objects in
might work but would be far from easy or canonical in nature.
From: Pascal J. Bourguignon
Subject: Re: Error Handling
Date: 
Message-ID: <87wsjwrz2p.fsf@hubble.informatimago.com>
Kent M Pitman <······@nhplace.com> writes:

> ···@informatimago.com (Pascal J. Bourguignon) writes:
>
>> > Better might be just to make it not work at all on abstract
>> > types (such as lists) and only work on "domain types" that have a
>> > well-defined "intentional meaning" for the purpose of human display
>> > (as is the case of conditions).
>> 
>> Yes, but nested lists are easy.
>
> I disagree.  What you mean to say is that it's possible to come up with 
> something that may seem easy out of context.
>
> The problem is that even just saying something in human language at all
> is not easy.  We found this out with y-or-n-p and yes-or-no-p, which cannot
> seriously be used by real applications in a portable way.  It can be used
> in debugging or by particular implementations where you have inspected what
> they do and you agree, but it has the option of using a typescript interface 
> or a windowed interface, and in some implementations it makes surprising 
> and stylistically confusing interfaces.  The only real way to get this kind 
> of thing right is to go at least the route of CLIM with present and accept 
> and lots of guidance about interfaces.
>
> Even with the tabbed interface you propose, the ability of the system
> to choose on a whim that it was going to use ascii-graphics bullets as
> opposed to rendered bullets as opposed to javascript-like active text
> would completely change the usability in an unpredictable way.  By contrast,
> a detailed worked-out convention for how to structure and merge objects in
> might work but would be far from easy or canonical in nature.

Well, I agree, it would have to be restricted in scope, (and as FORMAT
outputs text, it would also be restricted to BASE-CHAR output), but
this is no stronger a restriction as what we already have with
y-or-n-p or ~P (~P being quite English-specific, and outputing only
mere BASE-CHAR, without any HTML or other nicer-looking format).

So, given this restriction in scope, would ~H have been significantly
useful, compared to (pprint list-of-things)?  As a lisp programmer, I
can read sexps easily, the more so when pretty-printed, so I'd say no.
But for naive users, a default, limited-scope, BASE-CHAR
representation could still be useful.  Or could have been useful while
they used terminals.  Nowadays we can always do:

   (format t "<PRE>~H</PRE>" list-of-things)  ;-)


In anycase, if anybody needs something like that, there's ~/ to
implement it in a library:

   (format t "~/FORMAT-HTML-LIST/" list-of-things) 

So we won't miss ~H.
-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

THIS IS A 100% MATTER PRODUCT: In the unlikely event that this
merchandise should contact antimatter in any form, a catastrophic
explosion will result.
From: Vassil Nikolov
Subject: Re: Error Handling
Date: 
Message-ID: <snzskujlx58.fsf@luna.vassil.nikolov.name>
On Tue, 08 Jul 2008 20:49:18 +0200, ···@informatimago.com (Pascal J. Bourguignon) said:

| ...
| Nowadays we can always do:

|    (format t "<PRE>~H</PRE>" list-of-things)  ;-)

  Assuming we are Really Sure (TM) that the output produced by ~H will
  be well-formed and legal with regards to HTML markup, of course...

  ---Vassil.


-- 
Peius melius est.  ---Ricardus Gabriel.
From: John Thingstad
Subject: Re: Error Handling
Date: 
Message-ID: <op.udzo0cnhut4oq5@pandora.alfanett.no>
P� Tue, 08 Jul 2008 20:49:18 +0200, skrev Pascal J. Bourguignon  
<···@informatimago.com>:

> In anycase, if anybody needs something like that, there's ~/ to
> implement it in a library:
>
>    (format t "~/FORMAT-HTML-LIST/" list-of-things)
>
> So we won't miss ~H.

You can also access the pretty printer from format..

(format t "~<~W...~:>" ...
which allows you to set up your own pretty printer formats for data.

see *print-pprint-dispatch* copy-pprint-dispatch set-pprint-dispatch
For creating your own parsing rules.

Here is the full pretty printer documentation
http://portal.acm.org/citation.cfm?id=1039991.1039996

--------------
John Thingstad
From: Dan Weinreb
Subject: Re: Error Handling
Date: 
Message-ID: <9280afd2-a120-42be-9a48-603cac60a598@j22g2000hsf.googlegroups.com>
On Jul 8, 1:36 pm, Kent M Pitman <······@nhplace.com> wrote:
> ····@informatimago.com (Pascal J. Bourguignon) writes:
>

>
> The problem is that even just saying something in human language at all
> is not easy.  We found this out with y-or-n-p and yes-or-no-p, which cannot
> seriously be used by real applications in a portable way.  It can be used
> in debugging or by particular implementations where you have inspected what
> they do and you agree, but it has the option of using a typescript interface
> or a windowed interface, and in some implementations it makes surprising
> and stylistically confusing interfaces.

Aw, gee, Kent, I put these in back before we had GUI's at all.  We
just used Lisp from simple REPLs on simple computer terminals in those
days.
Things like mice and overlapping windows and such postdated their
invention. Yes, indeed, they're basically obsolete.  The version of y-
or-n-p in Swank, which prompts you in Emacs by talking to Slime, so
that it works nicely with the screen layout, is still quite viable, if
you happen to be in that debugging context; as you say, it's useful
during debugging.  These days I only write server code anyway so I
don't think about this stuff very much...
From: Kyle McGivney
Subject: Re: Error Handling
Date: 
Message-ID: <3b61cf06-9aa5-4a9c-bc74-40e2be8a58b2@y38g2000hsy.googlegroups.com>
>
> To revive:
>
> I was wondering what's a way to get more information about the error.
> other than just the error code.  For example, when an error occurs the
> debuggger gives a an explanation and the expression that went wrong,
> however, something like (pprint e) just prints #<simple error @.. > .
> Whats a way to access more information.
>
> Also, I'm having trouble printing errors in this form to a file.  I
> can't use (write-line error f) or (write-line (write-to-string .. )
> what else would work?

Write and write-to-string take keyword :escape, which might be useful
to you

What about format?
(format stream "~%~A encountered: ~A~%(lisp likes to print it like
this: ~s)"
  (type-of error) error error)

hope that helps
Kyle
From: Pascal J. Bourguignon
Subject: Re: Error Handling
Date: 
Message-ID: <87abgsuae9.fsf@hubble.informatimago.com>
Arun Ahuja <········@gmail.com> writes:
> I was wondering what's a way to get more information about the error.
> other than just the error code.  For example, when an error occurs the
> debuggger gives a an explanation and the expression that went wrong,
> however, something like (pprint e) just prints #<simple error @.. > .
> Whats a way to access more information.


In addition to PRINC'ing it,  you can sometimes get more information
by inspecting the error. (The method print-object of the error may not
display all the fields of the error).

In clisp, there are the debugger commands
   :e   to princ the error,
   :i   to inspect the error.

Sometimes there are implementation specific fields.  In a handler, you
can recover them with slot-value, if you can guess what package the
field name is in ;-)

-- 
__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: Dan Weinreb
Subject: Re: Error Handling
Date: 
Message-ID: <9239e973-65fb-4eca-937e-19bc692f47cc@z66g2000hsc.googlegroups.com>
On Jul 3, 3:15 pm, Arun Ahuja <········@gmail.com> wrote:
> On Jul 3, 1:40 pm, ····@informatimago.com (Pascal J. Bourguignon)
> wrote:
>
>
>
> > Arun Ahuja <········@gmail.com> writes:
> > > On Jul 3, 1:09 pm, Pascal Costanza <····@p-cos.net> wrote:
> > >> Arun Ahuja wrote:
> > >> > On Jul 3, 12:59 pm, Arun Ahuja <········@gmail.com> wrote:
> > >> >> On Jul 3, 12:21 pm, Pascal Costanza <····@p-cos.net> wrote:
> > >> >> I am trying to get this to work in a mapcar though.
>
> > >> Why?
>
> > > I'm not sure what the first 'Why?' is directed at,
>
> > Why are you trying to get this to work in a mapcar though?
>
> > Don't you know the eliza program?  You could learn from its
> > algorithms...
>
> > So, why do you want mapcar when you already have a perfectly working
> > iterative solution (using loop)?
>
> > > but to answer the
> > > rest:
>
> > > What I'd like is the function to run until it hits an error at a
> > > certain block, and then at the error, record the error and not exit
> > > the program but simply continue to the next block
> > > The code I wrote above, gets the error and exits rather then
> > > continuing.  
>
> > You are lying!  Your code works perfectly as you say you want it to
> > work:
>
> > C/USER[1]> (let ((text-list '("abc" "def" 42 "klm")))
> >              (flet ((process (x) (string-upcase x)))
> >                (let ((errors '()))
> >                  (values (mapcar (lambda (x) (handler-case (process x)
> >                                                (error (e)
> >                                                  (push (cons e x) errors)
> >                                                  nil)))
> >                                  text-list)
> >                          errors))))
> > ("ABC" "DEF" NIL "KLM") ;
> > ((#<SIMPLE-TYPE-ERROR #x207D0A76> . 42))
>
> > > right now, I am just trying this on a toy example trying
> > > to get it work
>
> > Why don't you show us your toy example?
>
> > --
> > __Pascal Bourguignon__                    http://www.informatimago.com/
>
> > "Specifications are for the weak and timid!"
>
> Yes, I have seem to have gotten it to work.  This forum takes some
> time for the posts to appear, but I posted, and then got it to work,
> (it was exiting for a separte reason) and then since my post hadn't
> shown up yet, I didn't post a correction.
>
> Thank you for the help.
>
> However, I am interested to hear why you would rather I use loop
> rather then mapcar?  Efficiency wise?  I have just personally
> preferred mapcar, and it was how the older non-error correcting
> function was written.  Also, thank you to the second poster for more
> information on restarts

No special reason.  mapcar and loop are both perfectly fine for what
you're doing, and the exception issues are basically the same for
both. It's mainly an issue of you preferred programming style.