Re: Run 2 Subroutines after a die
by jarich (Curate) on Oct 03, 2002 at 07:17 UTC
|
Try the following instead:
unless(open TST, ">>$var1")
{
One();
Two();
exit; # or die "Failed to open $var1: $!";
}
# rest of code here.
Then, if open fails you'll execute all the code in the block and then exit, which is what you're trying to do.
I alse get 1 at C:\Dev\MiscTests\sub.pl line 8
die is a function that takes a string and exits the program printing that message out with the line number and script name. In this case die is getting the result of your do{} as its string and printing it: "1". The result of your do just happens to be the return value of your subroutine Two, which is 1. (print returns 1 if it printed, and if there is no explicit return, the value of the last line (of code) in a subroutine is the return value).
If you try my suggestion from above, you won't get that any more.
Hope it helps.
jarich
Short answer to below
Yes, you're entirely correct. if( !cond ) is identical to unless( cond ). unless( cond ) { ...... } else { ......} is also legal (although there is no elsunless) but I'd encourage you to change any unless-then-else structures you might be tempted to write into if-then-else because that is much easier to read (mostly because that's what everyone else expects to see).
I prefer unless because I find that sometimes I don't see the ! in if( !$foo ). Readability kinda depends on the reader. unless does take more character presses... | [reply] [d/l] [select] |
|
Would I be correct in assuming that
if(! open TST, ">>$var1"){ } would just be another way of doing
unless(open TST, ">>$var1"){ }
If so, is this just another way of doing things or are there further benefits for using unless. I did once read that the code we use should be readable to humans and that the computers will still interpret our code. Is this a case of unless being easier to read than if not?
-----
Of all the things I've lost in my life, its my mind I miss the most.
| [reply] [d/l] [select] |
|
Would I be correct in assuming that
if(! open TST, ">>$var1"){ }
would just be another way of doing
unless(open TST, ">>$var1"){ }
Yes, you would.
If so, is this just another way of doing things or are there further benefits for using unless. I did once read that the code we use should be readable to humans and that the computers will still interpret our code. Is this a case of unless being easier to read than if not?
unless (foo) is just another way of writing if (not (foo)). It's up to you to decide what you find better readable.
- Yes, I reinvent wheels.
- Spam: Visit eurotraQ.
| [reply] [d/l] [select] |
|
As a point of preference, I prefer the unless blocks also.. I generally use them in just such a situation, and besides not missing the ! in the !condition, when I see an unless block I know that I'm generally handling failure. I know... in all conditional blocks, you're acting upon something either 'succeeding' or 'failing', but when I'm specifically putting something in there that is mainly sort-of error checking things that I'm assuming (files exist and are openable, etc.), I'll use unless.
-=rev=-
| [reply] [d/l] [select] |
Re: Run 2 Subroutines after a die
by robartes (Priest) on Oct 03, 2002 at 07:15 UTC
|
Hi AcidHawk,
your output includes 1 at C:\Dev\MiscTests\sub.pl line 8 because that's what die does:
die LIST;
prints LIST and appends the location in the program if LIST does not end in a newline. In your case, LIST is the do block, which returns 1, hence 1 at ....
Another way to call a number of functions or generally do stuff when dying, is to put said stuff in an END block:
open HELLO ">hello.txt" or die "Blerch: $!\n";
END
{
print "Endings are a sad business.\n";
}
Caveat: This may not be what you're looking for, as END blocks get executed whenever the program terminates, normally or abnormally. So they get executed even if your program completes normally and does not die anywhere.
CU Robartes-
Update: Added example code and caveat. | [reply] [d/l] [select] |
Re: Run 2 Subroutines after a die
by BrowserUk (Patriarch) on Oct 03, 2002 at 09:30 UTC
|
As always, TMTOWTDI... the comma operator can be useful for things like this.
#! perl -sw
use warnings;
use strict;
my $var1 = "aBadFileName?";
open TST, ">>$var1" or One(), Two(), die "Couldn't open $var1; $!\n";
print TST "Another Line\n";
close TST;
sub One
{
print "In Sub ONE\n";
}
sub Two
{
print "In Sub TWO\n";
}
__DATA__
C:\test>202447
In Sub ONE
In Sub TWO
Couldn't open aBadFileName?; Invalid argument
C:\test>
Cor! Like yer ring! ... HALO dammit! ... 'Ave it yer way! Hal-lo, Mister la-de-da. ... Like yer ring! | [reply] [d/l] |
Re: Run 2 Subroutines after a die
by bart (Canon) on Oct 03, 2002 at 09:37 UTC
|
{
local $SIG{__DIE__} = sub { One(); Two(); die shift; };
open TST, ">>$var1" or die "Can't open file: $!";
}
The code would also run if your script dies in the block for an unforeseen reason. Well, I can't imagine anything that could cause it in this simple example :-) but it's a useful technique for the toolbox. | [reply] [d/l] |
Re: Run 2 Subroutines after a die
by Dog and Pony (Priest) on Oct 03, 2002 at 07:46 UTC
|
This is one way of doing it (I assume your subs are cleanup routines rather than routines that should output stuff in the die message?):
open TST, ">>$var1"
or One(), Two(), die "Could not open '$var1': $!";
If that is any clearer may be disputed... I think it is, but some may disagree. Maybe '&&' instead of commas are more intiutive between the calls? That works too.
The '1' is, as pointed out, what do returns to your die for printing.
Hope that helps.
You have moved into a dark place.
It is pitch black. You are likely to be eaten by a grue. | [reply] [d/l] [select] |
Re: Run 2 Subroutines after a die
by jmcnamara (Monsignor) on Oct 03, 2002 at 08:00 UTC
|
In relation to your first question, the method that you are using seems fine.
In relation to your second question, the 1 in the die message is returned by the print in sub Two and then returned by the do{}.
To get a more useful error message you could do this:
open TST, "$var1" or die do {
One();
Two();
"Couldn't open file $var1: $!.\n";
};
--
John.
| [reply] [d/l] |
Re: Run 2 Subroutines after a die
by LEFant (Scribe) on Oct 03, 2002 at 16:58 UTC
|
Doing things after we die is unattainable except for the most exaltred of our order. Doing the most essential things before we die should be our goal. It would seem to me that no more often that it would be called another sub might be wise:
#!perl.exe
use strict;
use warnings;
my $var1 = "test.txt";
open TST, ">>$var1" or scram($var1, $!);
print TST "Another Line\n";
close TST;
sub One
{
print "In Sub ONE\n";
}
sub Two
{
print "In Sub TWO\n";
}
sub scram{
my ($filename, $exitmsg ) = @_;
One();
Two();
die "Error opening $filename: $exitmsg\n";
}
| [reply] [d/l] |
Re: Run 2 Subroutines after a die
by kabel (Chaplain) on Oct 03, 2002 at 19:14 UTC
|
here is another way of doing things ;) unfortunately i was unable to implement it - it just did not work - but i know it is possible:
the Fatal.pm module allows to make some function calls die if they return undef - handy for e.g. open etc. i thought i could do this for the die call for myself (for example, call two functions named One () and Two () before dieing :), looked at the modules source - the rest can be read above...
perhaps one can put here the correct way of doing this? or is this way considered more harmful? | [reply] |
|
ok here is another way that is not like the one i found in Fatal.pm, but it seems to work either.
use strict;
use warnings;
use subs qw(die);
# install my new die code
sub die { One (); Two (); print "Die.\n"; CORE::die @_; }
my $filename = "this file does not exist";
open (FH, $filename) or die "$filename: $!";
# do something
close (FH);
sub One { print "One . ";}
sub Two { print "Two . ";}
| [reply] [d/l] |