KILNA has asked for the wisdom of the Perl Monks concerning the following question:

I've been making a lot of deploy scripts lately. They're the sort of thing where you run through a sequence of steps, and if any of the steps fail you want it to bail out and tell you what it failed on. I know a lot of ways I *could* accomplish this goal. I could follow every statement with a die and the reason for the death:
{ foo() || die "foo() didn't return true"; bar() || die "bar() didn't return true"; ... and so on }
But really, the only thing that's significant is the calls to foo() and bar(). The dies are just stating information that's already there, if we give the block some context. I am pondering writing a source filter so that I can wrap every statement with an '|| die "$statement returned false!"', but this seems really dirty. Ideally I'd like a syntax like:
every { block of statements } run { block to be run after each statement in 1st block }
So, to emulate the above example:
every { foo(); bar(); ... } run { my $command = shift; # String representation of statement my $result = shift; # What the statement returned die "Command $command did not return true!" unless $result; }
Am I crazy for even wanting something like this? Is there something out there that can accomplish the goals of syntactic simplicity (not burdening the straight sequence of statements with extra baggage) while still giving the ability to do something after each statement?

-- KILNA - music for cyborgs - http://www.kilna.com

Replies are listed 'Best First'.
Re: Doing the same thing after each statement in a block...?
by ikegami (Patriarch) on May 19, 2009 at 20:40 UTC

    If the subs all take the same args:

    for (qw( foo bar )) { no strict 'refs'; $_->() || die "Command $_ did not return true!\n"; }

    If the subs take inconsistent args:

    for ( [ foo => \&foo ], [ bar => sub { bar($arg) } ], ) { my ($name, $sub) = @_; $sub->() || die "Command $name did not return true!\n"; }

    Those aren't exactly pretty. autodie is probably much better. In future versions, you'll even be able to give it hints as to what is an error or not. (For example, maybe returning zero is an error for foo(), but it isn't for bar()).

    It's still new, but it's actively developed and maintained, and it has been made part of core Perl (but it's available independently as well).

Re: Doing the same thing after each statement in a block...?
by DStaal (Chaplain) on May 19, 2009 at 20:30 UTC

    I'd say take a look at autodie and/or IPC::System::Simple, depending on exactly what you are doing. You'll probably have to write a bit of code to get the messages you want, but it won't be inline with the rest.

Re: Doing the same thing after each statement in a block...?
by morgon (Priest) on May 19, 2009 at 22:10 UTC
    I am pondering writing a source filter so that I can wrap every statement with an '|| die "$statement returned false!"', but this seems really dirty.
    Why?

    For my taste it would be a perfectly legitimate use of a source-filter.