Re: On the case for exception-based error handling.
At 10:26 AM 8/27/00 -0400, Bennett Todd wrote: So I'd expect instead use Fatal qw(:arithmetic :io ...); Therefore the default (to get the current behavior) would be that some of the classes had Fatality enabled and others didn't? And if Fatal supported unimport, then the default could be inverted with use Fatal qw(:io ...); no Fatal qw(:arithmetic); Bingo, yes. I will make appropriate changes to RFC 80. You might think about whether RFC 70 needs to be changed. The ramifications of some of these things are sufficiently important that drawing attention to them might be a good thing. In this case, note that Perl 6 will need to spell out which core exceptions are by default fatal (eg, :arithmetic) and which aren't. Although RFC 70 doesn't have to do that. Oh, reminds me, I forgot to respond to: I beat you to it. While RFC 70 was intended to just request that it be possible to finish Fatal.pm so it works as intended and desired, it does mention: If [the finishing-up of Fatal.pm, after fixing the busted core] were a success, then the requested category could also be posted into a testable variable, allowing module authors who wished to to automatically support this functionality as well. Got anything in mind? $^something? -- Peter Scott Pacific Systems Design Technologies
Re: On the case for exception-based error handling.
Glenn Linderman wrote: Tony Olekshy wrote: Glenn Linderman wrote: actually wrapping a bunch of code inside a try block affects how that code reacts to die, thus affecting the behavior of the program that previously used die to mean terminate the program. Hang on, this can't be true. To quote from RFC 88: try { may_throw_1 } catch may_throw_2 = { may_throw_3 } finally { may_throw_4 } is exactly the same as (assuming traditional Perl semantics): eval { may_throw_1 }; my $exception = $@; if ($exception) { my $test = eval { may_throw_2 }; $@ and $exception = $@; if ( ! $@ and $test ) { eval { may_throw_3 }; $exception = $@; } } eval { may_throw_4 }; ($exception ||= $@) and die $exception; How can this affect how code reacts to die? It reacts the same as with eval, whether wrapped in a try or not. Say I had: do_something(); now I wrap it in a try: try { do_something(); } this is equivalent to: eval { do_something(); }; my $exception = $@; $exception and die $exception; Which is *exactly* the same as bare do_something(); as per Perl 5. OK, this example clearly demonstrates something. 99% of the catch clauses in the world should be conditional, handling only those specific exceptions that it knows about, and knows it can handle. The "catch-all" (unconditional catch of anything), is error prone; [...] a "catch-all" might bite off _lots_ more than it should chew. Maybe "catch-all"s that do something and then re-throw would be relatively safe. Yes! Only when one knows an awful lot about what's going on in the body of a try is a catch-all that does much more than set a state variable and re-throw possibly safe, because by definition once an exception has raised there are a bunch of things one shouldn't make too many assumptions about. Here is one possibly safe example: try { $y = ( $a * $x * $x + $b * $x + $c ) / $d; } catch { $y = undef; } but this would be even safer: try { $y = ( $a * $x * $x + $b * $x + $c ) / $d; } catch Exception::CORE::Math = { $y = undef; } The only case where catch really should be unconditional (and not just re-throw) is when top-level (some sort of main.pl) code wraps the whole shebang in a try with this type of explicit purpose: try { the_whole_shebang() } catch { pass_to_client($@-show(label = 1, trace = 1)) } Where pass_to_client may be print + exit; Yours, c, Tony Olekshy
Re: On the case for exception-based error handling.
Peter Scott wrote: Yes, we get breakage; the user expects die to be trapped by eval. It still would be. Users of Error.pm also expect it to be trapped by catch. It still would be, if you 'use Error.pm'. I do not think we should maintain die/eval as a separate mechanism from try/catch; I do, unless some fancy footwork is done to avoid accidentally catching fatal errors in catch-all clauses. And that makes for added complexity. I think they should be synonymous for interoperation (so users aren't forced to migrate an entire application from one method to the other just because one module uses the other method). Handle this with wrapper modules if needed. And see if p52p6 can convert standard uses of Try.pm and Error.pm to the new mechanism, to avoid the need for most of the wrapper modules. This means that die can be trapped by catch, and that throw can be trapped by eval. Blecch. Orthogonality of the mechanisms is easier to understand than funny rules, special cases, and syntactical magic. -- Peter Scott Pacific Systems Design Technologies -- Glenn = There are two kinds of people, those who finish what they start, and so on... -- Robert Byrne ___ Why pay for something you could get for free? NetZero provides FREE Internet Access and Email http://www.netzero.net/download/index.html
Re: On the case for exception-based error handling.
At 02:37 PM 8/23/00 -0700, Glenn Linderman wrote: This means that die can be trapped by catch, and that throw can be trapped by eval. Blecch. Orthogonality of the mechanisms is easier to understand than funny rules, special cases, and syntactical magic. But that *is* being orthogonal. That's how Error.pm implemented it and it makes perfect sense. Nothing in RFC 88 precludes die and throw from sharing the same underlying code, or simlarly catch/eval. I think it should make it clear that they *are* the same thing. -- Peter Scott Pacific Systems Design Technologies
Re: On the case for exception-based error handling.
Chaim Frenkel wrote: Tony Olekshy wrote: If no exception is in scope Perl should continue to generate and propagate exceptions (die and $@) as it does now, so we don't break tradition. No, that should be the difference between die and throw. Die is immediately fatal. (i.e. current semantics) throw is new and does the magic. We get no breakage that way. But if die and eval are supposed to do keep doing what they do now, RFC 88 doesn't impact them at all. In fact it depends on what they do now. To quote from RFC 88: Although the following code using the new mechanism: try { may_throw_1 } catch may_throw_2 = { may_throw_3 } finally { may_throw_4 } can be written in Perl 5 like this: eval { may_throw_1 }; my $exception = $@; if ($exception) { my $test = eval { may_throw_2 }; $@ and $exception = $@; if ( ! $@ and $test ) { eval { may_throw_3 }; $exception = $@; } } eval { may_throw_4 }; ($exception ||= $@) and die $exception; the opportunity for flow-control errors increases. On the other hand, if eval is suddenly supposed to stop catching so-called non-fatal errors, then all hades breaks loose. Trust me. Yours, c, Tony Olekshy
Re: On the case for exception-based error handling.
--On 22.08.2000 10:48 Uhr -0700 Glenn Linderman wrote: This probably won't work. What would you return exactly? Also, there's plenty of chance that the return value could interfer with the regular return values of that function... This will never be possible without work done by the module author so the return value plays nicely. ... Hence, exception handling (with or without catch phrases) allows the normal, non-error case to be coded more simply both when you don't care about catching errors (die), and when you do. Hmm.. I don't know how this paragraph relates to my comments (even though it's a nice overview of the advantages from exceptions - which I'm already convinced of after being forced to program in Java for several years.) What I was talking about is that I cannot imagine that the perl core itself magically transforms exceptions into return values as someone else requested. "enabling/disabling fatality for exceptions with a pragma"... if the idea is that control continues linearly past a throw, then sub/module authors must write twice the error handling logic, which is painful. If it means No - the sub returns as if it has correctly thrown the exception, but if the exception really propagates to the top most level, it will be ignored instead of die'ing. This is really the same as a try/catch block around my whole program just not that ugly. that the destination of the throw is bounded to some boundary, that boundary must be defined... so I guess that's a scoped pragma, so the syntax would be something like { use no_fatal_throws; ignore_my_errors ( @params ); } That's just about exactly the same length and complexity as the null catch phrase above, which does exactly the same job. What I was actually requesting was a small pragma which simply turns off all fatality, in the whole program, similar to what $SIG{__DIE__} currently is able to do, without the need to span a try/catch block across my whole main program - I simply do not like the look and feel of that. Even though this has global effects, it's not necessarily evil, we should only ensure that it cannot be used from within a .pm -- Markus Peter - SPiN GmbH [EMAIL PROTECTED]
Re: On the case for exception-based error handling.
At 02:00 PM 8/22/00 -0600, Tony Olekshy wrote: Peter Scott wrote: I actually see nothing wrong in division returning undef for a dividend of 0. It's just as easy to check as doing an eval. Please don't do this. I would have to check every divide in all my code, since no fatal is the default! Leave the current version of Perl's best guess as to what it should die on alone, unless use fatal is in scope. Consider this: $amount_i_owe_you = $gross_amount / $discount_rate - $paid; If $discount_rate is accidentally undef and $paid is $100, then the $amount_i_owe_you is now -$100. I don't see my cheque yet ;-) But surely you have to be consistent. I understood Chaim's point to be that he wanted no exceptions if he didn't ask for them. If the core currently dies where it could return and set $!, then it is being inconsistent, since this is not an error that prevents perl from continuing. How can Chaim or anyone else write a program and know that it won't die if we allow such things to continue? I suppose we could have a use Fatal qw/legacy/ Yuk. -- Peter Scott Pacific Systems Design Technologies
Re: On the case for exception-based error handling.
On Tue, 22 Aug 2000, Glenn Linderman wrote: I'm suddenly intuiting that maybe you want to continue execution after the sub call that caused the throw. But if you continue, you won't have the return values from the sub call. Where should the continuation take place for something like: l1: $a = foo ( bar ( $b )); l2: baz ( $a ); l3: in the two different cases that bar throws, and that foo throws? If you continue "immediately after" the sub call, and bar throws, foo is likely to get bad parameters and also fail. And if you say the next statement after a Yes, that's true, but I'm not talking about such cases. Your above example would result in garbage in, garbage out which is ok if I want to circumvent the exception system. Maybe it's easier to understand if I explain what I do not want to have ;-) I'd normally use such a pragma when I want to write a small hack, not a large project. What I fear are that certain modules will die on me even on stuff comparable to e.g. unlink in side effects - as they simply want to throw an exception as a means of reporting "file is not there anyway" - which I absolutely do not care about... E.g. in Java writing small hacks is impossible because you'll spend half your time adding try/catch blocks around stuff... Perl is a bit better in that respect - it allows me the choice to forget completely about exceptions or having the same trouble as in Java What I request is probably similar to the no Fatal pragma someone proposed. The only thing I dislike about no fatal is that modules are supposed (are they really?) to return error return values then - and what I'd like to have is still that I CAN catch exceptions at some points, but I need not to. If I don't check it, I'll simply get an undef return value, but I still have the choice to check one or two possible exceptions without enabling/disabling all that myself. The current definition of use fatal/no fatal would not allow this I think as suddenly those modules could stop throwing exceptions, so I'd end up enable/disabling use fatal all the time... Another way to achieve the same result would be to NOT get rid of the try part of try/catch and then try automatically implies use fatal for that block... -- Markus Peter [EMAIL PROTECTED]
RE: On the case for exception-based error handling.
[snip] -Original Message- From: Markus Peter [mailto:[EMAIL PROTECTED]] Another way to achieve the same result would be to NOT get rid of the try part of try/catch and then try automatically implies use fatal for that block... -- Markus Peter [EMAIL PROTECTED] [/snip] So that was: Any exception raised in a try will be fatal unless caught? -Corwin
RE: On the case for exception-based error handling.
At 04:06 PM 8/22/00 -0500, Brust, Corwin wrote: [snip] -Original Message- From: Markus Peter [mailto:[EMAIL PROTECTED]] Another way to achieve the same result would be to NOT get rid of the try part of try/catch and then try automatically implies use fatal for that block... So that was: Any exception raised in a try will be fatal unless caught? It already is (RFC 88). -- Peter Scott Pacific Systems Design Technologies
Re: On the case for exception-based error handling.
"PS" == Peter Scott [EMAIL PROTECTED] writes: PS From the reactions on this thread so far I am wondering whether the PS message I sent out about it when it had a different name got PS through. Relevant excerpt: PS Well, you could certainly have a pragma that makes throw set $! to the PS message and does a return undef. But that will only return from the PS current subroutine; there could be a bunch of module subroutines between PS that one and the module user. Asking module programmers to keep straight PS two possible flows of control in error situations, no less, is asking for PS trouble. If you think it can be made easier, can you show an example? Actually, why not simply unwind the call stack to the routine that has the pragma active. sub foo {use exception; baz()} sub baz { throw "a fit" } sub bar { no exception; foo(); } The unwind logic would treat a scope with no exception set _as if_ each call were wrapped in at try block. PS ***But it's entirely up to each programmer whether or not they use PS Fatal-checking*** This is the Perl way anyway. Fatal checking, is for core functions. And optional for module authors. Then Fatal.pm and exception.pm could possibly be consolidated. chaim -- Chaim FrenkelNonlinear Knowledge, Inc. [EMAIL PROTECTED] +1-718-236-0183
Re: On the case for exception-based error handling.
Chaim Frenkel wrote: Actually, why not simply unwind the call stack to the routine that has the pragma active. sub foo {use exception; baz()} sub baz { throw "a fit" } sub bar { no exception; foo(); } Yes. The unwind logic would treat a scope with no exception set _as if_ each call were wrapped in at try block. I don't think so. If no exception is in scope Perl should continue to generate and propagate exceptions (die and $@) as it does now, so we don't break tradition. PS ***But it's entirely up to each programmer whether or not they use PS Fatal-checking*** This is the Perl way anyway. Fatal checking, is for core functions. And optional for module authors. Yes. Then Fatal.pm and exception.pm could possibly be consolidated. Yes. I like something like this chaim -- Chaim FrenkelNonlinear Knowledge, Inc. [EMAIL PROTECTED] +1-718-236-0183