all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* non-local exits with signal and condition-case
@ 2013-06-02 16:24 Nic Ferrier
  2013-06-02 18:52 ` Stefan Monnier
  0 siblings, 1 reply; 5+ messages in thread
From: Nic Ferrier @ 2013-06-02 16:24 UTC (permalink / raw)
  To: emacs-devel

Is it just me or is catch annoying for some non-local exits?

When I do non-local exits, which isn't often, I mostly want to
non-locally exit and pass some data back.

Maybe this is the fault of my exposure to Java programming and using
exceptions for flow control? Anyway. I find that catch rarely fulfils my
needs.

It's possible to use signal and condition-case to achieve the effect
that I most often want and I do use them.

But making new signals is slightly annoying because you need to add 2
different properties to a symbol.

I propose a simple macro to make this easier:

 (defmacro defsignal (err-symbol inherits-list message)
   (let ((errv (make-symbol "err-v")))
     `(let ((,errv ,err-symbol))
        (put ,errv
             'error-conditions
             (quote ,inherits-list))
        (put ,errv
             'error-message
             ,message))))

One uses it like this:

 (defsignal :nictest-blah (:nictest :nictest-blah) "blah!")

I'm not sure where to put this. I could package it. But I'm collecting a
list of these things (noflet, let-while, etc...) and gradually it seems
I'm inventing my own lisp.

This one though seems to be a genuine gap in elisp.

Is there any interest in core-ing it?



Nic



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: non-local exits with signal and condition-case
  2013-06-02 16:24 non-local exits with signal and condition-case Nic Ferrier
@ 2013-06-02 18:52 ` Stefan Monnier
  2013-06-02 21:33   ` Nic Ferrier
  0 siblings, 1 reply; 5+ messages in thread
From: Stefan Monnier @ 2013-06-02 18:52 UTC (permalink / raw)
  To: Nic Ferrier; +Cc: emacs-devel

> Maybe this is the fault of my exposure to Java programming and using
> exceptions for flow control? Anyway. I find that catch rarely fulfils my
> needs.

Could you explain in more detail what you do that doesn't work well
with catch?

> But making new signals is slightly annoying because you need to add 2
> different properties to a symbol.

Using signals is clearly not a good idea if what you want is just
a non-local exit.  BTW, you might like the `cl-return' macro as well
(to use within `cl-block's).

>  (defmacro defsignal (err-symbol inherits-list message)
>    (let ((errv (make-symbol "err-v")))
>      `(let ((,errv ,err-symbol))
>         (put ,errv
>              'error-conditions
>              (quote ,inherits-list))

You probably want to cons `errv' in front of inherits-list.

>         (put ,errv
>              'error-message
>              ,message))))

FWIW, I wouldn't mind introducing such a macro.  Not for the use of
non-local exits, but to make it easier to define new error conditions.

I would also welcome changes to make the "error-message" part more
flexible (e.g. be able to use a function, maybe).

> I'm not sure where to put this.

We could add it to subr.el (tho I'd call it define-signal).


        Stefan



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: non-local exits with signal and condition-case
  2013-06-02 18:52 ` Stefan Monnier
@ 2013-06-02 21:33   ` Nic Ferrier
  2013-06-03  0:02     ` Stefan Monnier
  2013-06-03 15:54     ` Davis Herring
  0 siblings, 2 replies; 5+ messages in thread
From: Nic Ferrier @ 2013-06-02 21:33 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:

> Could you explain in more detail what you do that doesn't work well
> with catch?

I'll use a specific example (but it really is indicative, I find this
happens to me more often that not doing non-local exits).

This is a heavily simplified version of something I just wrote for the
new elnode based emacswiki:

 (defun make-page (page-name)
   (let ((buf (find-file-noselect page-name)))
     (with-current-buffer buf
       (when (re-search-forward "^REDIRECT \\(.*\\)" nil t)
         (throw :redirect (match-string 1))))
     ;; Otherwise we need to send the page
     (start-page buf)
     (send-page (buf->html buf))))

 (defun serve-page (http)
   (let ((page-name (get-page http)))
     (let ((value 
            (catch :redirect
              (make-page page-name))))
       (when value
         (send-redirect http value)))))


Note how the throw is being used to communicate place and value but in
the catch I only need to know that there was an exceptional condition.

This is the essence of the problem I think. catch does not support, of
itself, exceptional conditions. You have to overlay support for them
with extra typing.

In this example, I could be in trouble is make-page ever returns
anything. So I could throw a cons with a type indicator (say, :redirect)
and check for the type in the when. But that is a lot more work.

I've played with making macros around catch but in the end they seem
little better than having a signal. Is there a technical reason why a
signal is bad compared to catch/throw?



> BTW, you might like the `cl-return' macro as well
> (to use within `cl-block's).

I strongly dislike sprinkling cl- namespace through my code. It makes it
much less readable to me.


>>  (defmacro defsignal (err-symbol inherits-list message)
>>    (let ((errv (make-symbol "err-v")))
>>      `(let ((,errv ,err-symbol))
>>         (put ,errv
>>              'error-conditions
>>              (quote ,inherits-list))
>
> You probably want to cons `errv' in front of inherits-list.

I thought about that before I sent it - I think you are probably
right. But my understanding is that you don't need the symbol to be
present; you can disassociate the symbol used to send the signal from
the symbol(s) used to capture it.

I think (as you suggest) a define-signal form should probably not support that
directly because it seems quite counter intuitive.


> FWIW, I wouldn't mind introducing such a macro.  Not for the use of
> non-local exits, but to make it easier to define new error conditions.
>
> I would also welcome changes to make the "error-message" part more
> flexible (e.g. be able to use a function, maybe).
>
>> I'm not sure where to put this.
>
> We could add it to subr.el (tho I'd call it define-signal).

Shall I send patches then?



Nic



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: non-local exits with signal and condition-case
  2013-06-02 21:33   ` Nic Ferrier
@ 2013-06-03  0:02     ` Stefan Monnier
  2013-06-03 15:54     ` Davis Herring
  1 sibling, 0 replies; 5+ messages in thread
From: Stefan Monnier @ 2013-06-03  0:02 UTC (permalink / raw)
  To: Nic Ferrier; +Cc: emacs-devel

> This is a heavily simplified version of something I just wrote for the
> new elnode based emacswiki:

Oh, I misunderstood, then: you're simulating "exceptions", which are
called "signals" in Elisp, so you definitely want to use `signal' and
`condition-case' here, rather than catch/throw.

The only inconvenient is that signal names are global, so you need to
use a name of the form "<prefix>-redirect".  I guess you could use an
uninterned signal name, but it might be tricky to make use of that in
a convenient way.

>> You probably want to cons `errv' in front of inherits-list.

> I thought about that before I sent it - I think you are probably
> right.  But my understanding is that you don't need the symbol to be
> present; you can disassociate the symbol used to send the signal from
> the symbol(s) used to capture it.

Yes, if you don't put `errv' in there, indeed you dissociate the two, so
you can't catch an "errv" with "errv" but only with one of its parents.

> I think (as you suggest) a define-signal form should probably not
> support that directly because it seems quite counter intuitive.

Exactly.  While it's technically possible, no signal does that and
I can't think of any situation where someone would want to make use of
such a "feature".  So it's more likely to be a source of bugs and
bug-reports than anything else.

>> We could add it to subr.el (tho I'd call it define-signal).
> Shall I send patches then?

Yes.  Please send them to bug-gnu-emacs@gnu.org.


        Stefan



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: non-local exits with signal and condition-case
  2013-06-02 21:33   ` Nic Ferrier
  2013-06-03  0:02     ` Stefan Monnier
@ 2013-06-03 15:54     ` Davis Herring
  1 sibling, 0 replies; 5+ messages in thread
From: Davis Herring @ 2013-06-03 15:54 UTC (permalink / raw)
  To: Nic Ferrier; +Cc: Stefan Monnier, emacs-devel

> In this example, I could be in trouble is make-page ever returns
> anything. So I could throw a cons with a type indicator (say, :redirect)
> and check for the type in the when. But that is a lot more work.

In this case, why not just have make-page return nil if it sent the page
and the redirect target otherwise?  If it had some other return value
that you wanted to ignore in this case, on the other hand, you can just
put "nil" as an additional form in the catch.  (Granted: these functions
are unusual in that they are side-effect-only.)

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.



^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2013-06-03 15:54 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-06-02 16:24 non-local exits with signal and condition-case Nic Ferrier
2013-06-02 18:52 ` Stefan Monnier
2013-06-02 21:33   ` Nic Ferrier
2013-06-03  0:02     ` Stefan Monnier
2013-06-03 15:54     ` Davis Herring

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.