On Jan 2, 2008 5:14 AM, Dr.Ruud <[EMAIL PROTECTED]> wrote: > "Chas. Owens" schreef: > > Adarsh Srivastava: > > >> 1. Perl doest seem to catch errors like divide-by-zero error. Eg: > >> for an input expression like 99 / 0, it simply displays nothing as > >> output. (no errors thrown). > > > > Not true. If you aren't seeing the errors then you aren't checking $@ > > like I did in my example. > > Sorry Chas, for hijacking your reply. > > I never understood why checking $@ is done, when checking the eval > return value itself is available (and it always is, or can be made so). > > eval { > ... > 1; > } or do { > ... > }; > > The $@ can be set in many ways. Some coders even test $@ with regexes. > Let's try to get rid of all that, just as with bareword filehandles and > 2-argument opens.
Um, what sets $@ besides eval? Take a look at perldoc perlvar: perldoc perlvar $@ The Perl syntax error message from the last eval() operator. If $@ is the null string, the last eval() parsed and executed correctly (although the operations you invoked may have failed in the normal fashion). (Mnemonic: Where was the syntax error "at"?) If you have code that is setting $@ then you have bad code; Perl can only protect you from shooting yourself in the foot so much. However, it is possible to have more than one eval or even evals you don't know about in subroutines, but if your if (or given, see below) is right next to an eval, then there is no way* for it to be set other than by that eval: #!/usr/local/ActivePerl-5.10/bin/perl use strict; use warnings; use feature ':5.10'; sub set_error_at { $@ = "foo is bar\n"; } say "\$@ is [EMAIL PROTECTED]"; set_error_at(); say "\$@ is [EMAIL PROTECTED]"; eval { set_error_at() }; say "\$@ is [EMAIL PROTECTED]"; Of course, you can't trust that $@ will stay the same after that point, but you also can't trust that $! or $^E will have useful information except right after an event that you know caused an error. That is the nature of global error message variables. snip > > This means that you should rewrite > > my $dbh = eval { ... }; > if ($@) { > ....; # error > } > > to something like > > my $dbh; > eval { > $dbh = ...; > 1; > } or do { > ...; # error > } > > (or use an if/else construct of course) > > -- > Affijn, Ruud > > "Gewoon is een tijger." snip The $@ variable is not just used for checking to see if an error occurred; that isn't even its primary purpose. Its reason for existing is that it holds the error that actually occurred. The fact that it makes it easy to check if an error occurred is just a nice benefit. What exactly should the code above do if there is an error? If the database connection timed out we should wait a reasonable (and random) amount of time and try again. If the database connection failed because we have the wrong password there is no point in trying the faulty password again. This means you must inspect the contents of [EMAIL PROTECTED] If you are already going to do that why not go ahead and use $@ to detect that an error occurred at all? This saves you from having to put the constant 1 at the end of your eval (a waste of a line as far as I am concerned). In fact, now have the given control structure, it makes even more sense to use $@: #warning, untested code and bad regexes my $dbh; my $attempts = MAX_DB_CONNECT_ATTEMPTS; DBI_CONNECT: until ($dbh = eval { DBI->connect('dbi:foo:dbname=bar', 'user', 'pass', { RaiseError => 1 }) }) { given ($@) { when (/connection timed out/) { die $@ unless --$attempts; sleep(3 + int rand 3) } when (/password/) { die $@ } when (/other thing/) { recover_somehow() } default { die "unknown error: [EMAIL PROTECTED]" } } } * Well, theoretically a signal handler could be called in the brief span of time between the eval and the if and $@ could be set, but not only is highly unlikely, it is also bad practice to be calling an eval (or doing anything non-trival for that matter) in a signal handler. ** Well, to be fair you could use the contents of DBI->errstr, but that is only in the case of the DBI errors. Things like a divide-by-zero exception can only be caught by [EMAIL PROTECTED] -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] http://learn.perl.org/