views:

192

answers:

4

I want to check the results of an operation in the Net::FTP Perl module rather than die.

Typically you would do:

$ftp->put($my_file)
  or die "Couldn't upload file";

But I want to do something else instead of just dying in this script so I tried:

$ftp->put($my_file)
  or {
      log("Couldn't upload $my_file");
      return(-1);
  }

log("$my_file uploaded");

But Perl complains of compilation errors saying:

syntax error at toto.pl line nnn, near "log"

which is the second log in my code fragment.

Any suggestions greatly appreciated.

cheers,

A: 

use do.

here is small code snippet:


sub test {
    my $val = shift;
    if($val != 2) {
     return undef;
    }
    return 1;
}

test(3) || do {
      print "another value was sent";
};
Geo
+17  A: 

do is what you're looking for:

$ftp->put($my_file)
  or do {
      log("Couldn't upload $my_file");
      return(-1);
  };

log("$my_file uploaded");

But this is probably better style:

unless( $ftp->put( $my_file )) { # OR if ( !$ftp->put...
      log("Couldn't upload $my_file");
      return(-1);
}

If you just want to return an error condition, then you can die and use eval in the calling func.

use English qw<-no_match_vars>; # Thus, $@ <-> $EVAL_ERROR

eval { 
    put_a_file( $ftp, $file_name );
    handle_file_put();
};

if ( $EVAL_ERROR ) { 
    log( $EVAL_ERROR );
    handle_file_not_put();
}

and then call

sub put_a_file { 
    my ( $ftp, $my_file ) = @_;
    $ftp->put( $my_file ) or die "Couldn't upload $my_file!";
    log( "$my_file uploaded" );

}

Axeman
minor typo: $ftp-put should be $ftp->put
Chas. Owens
Make sure you follow Axeman's advice with the '-no_match_vars'; see http://perldoc.perl.org/English.html for details. Alternatively, you can use $@ for $EVAL_ERROR, but $EVAL_ERROR is easier to read.
Robert P
Thanks, Robert, but I think our fixes crashed. :)
Axeman
+3  A: 

or do{}; always makes my head hurt. Is there a good reason to use "or" syntax (which I admit using a lot for one liners) vs "if" (which I prefer for multi liners)?

So, is there a reason to use or not use one of these methods in preference of the other?

foo()
  or do {
    log($error);
    return($error);
  };
log($success);

if (!foo()) {
  log($error);
  return($error);
}
log($success);
jj33
I would use unless (foo()) { instead of if (!foo()). I use the or do {} when the function call stretches across many lines likeDBI->connect( 'dbi:foo:dbname=bar', $user, $pass, { AutoCommit => 0, ChopBlanks => 1, }) or do { #handle error}
Chas. Owens
The "or do" post-statement is my preferred way when it is for error checking. It displays the actual action as intended, and then appends something extra to handle errors. "unless" (and "if") put too much emphasis on the error handling, as if generating an error was the thing _intended_.
Svante
So the answers seem to be because one way makes more sense or looks better (I see the point about using or do{} when the action spans multiple lines, but I don't buy the "too much emphasis on error handling" logic). Ultimately both of these answers have to do with aesthetics and not performance...
jj33
Right, nothing to see here performance-wise. If you are looking at performance at this level, you are doing it wrong.
ysth
A: 

I'm having a hard time understanding why this needs to be wrapped up in a do. Is there a reason that this isn't sufficient?

my $ftp_ok = $ftp->put( $my_file )
  or log("Couldn't upload $my_file" ) and return -1;

log("$my_file uploaded") if $ftp_ok;

This assumes that the put function doesn't always return undef on success.

mnology
do {..} groups things in a more readable way. Stringing together conditionals without parenthesis or blocks makes you stop and figure out what is going on (and wondering "Hmm, can log() return false?).
runrig
That assumes log() returns true. Better: or log("..."), return -1;
ysth