in reply to Re^2: exiting a subroutine neatly
in thread exiting a subroutine neatly

speaking of which, c-style error checking/indicating return codes are a pita when you have Try::Tiny/die/eval/Throwable
use Try::Catch qw/ try catch finally /; sub foo { ... try { fooFoo($ssh); } catch { warn "warn cought one: $_"; }; $ssh->exit_session; $ssh->close_session; } sub fooFoo { my ($ssh) = @_; if ( !$ssh->start_session($ssh_host) ) { MyErr->throw("ERROR connecting to $ssh_host"); } my ( $ret, $err ) = $ssh->execute( 'command1', 'expect1' ); if ( $err || $ret =~ /Unknown command:/m ) { MyErr->throw({err => $err, ret => $ret, execute => [ 'command1 +', 'expect1' ] ); } my ( $ret, $err ) = $ssh->execute( 'command2', 'expect2' ); if ( $err || $ret =~ /Unknown command:/m ) { MyErr->throw({err => $err, ret => $ret, execute => [ 'command2 +', 'expect2' ] ); } return; } { package MyErr; use Moo; with 'Throwable'; has err => (is => 'ro'); has ret => (is => 'ro'); has execute => (is => 'ro'); 1; }

Replies are listed 'Best First'.
Re^4: exiting a subroutine neatly (Throwable)
by salva (Canon) on May 05, 2015 at 10:51 UTC
    But then, you are using exceptions for flow control when what you really need is some kind of unwind-protect. For instance Guard.
    use Guard qw(scope_guard); sub ssh_execute_and_check { my $ssh = shift; my ($ret, $err) = $ssh->execute(@_); if ( $err or $ret =~ /Unknown command:/m ) { MyErr->throw({err => $err, ret => $ret, args => [@_]}); } return $ret; } sub foo { $ssh->start_session($ssh_host) or MyErr->throw(...); scope_guard { $ssh->exit_session; $ssh->close_session; }; my $ret1 = ssh_execute_and_check($ssh, 'command1', 'expect1'); my $ret2 = ssh_execute_and_check($ssh, 'command2', 'expect2'); ... 1; }

      But then, you are using exceptions for flow control when what you really need is some kind of unwind-protect. For instance Guard.

      How do you figure?

      I raise an exception in case of error -- this isn't using exceptions for flow control, exceptions aren't used to return a value from the sub

      so I included both ret and err in the exception -- this isn't using exceptions for flow control ... I simply didn't scrutinize the if statement beyond counting/naming the vars which I included in the exception

        How do you figure?

        Looking at your code:

        sub foo { ... try { fooFoo($ssh); } catch { warn "warn cought one: $_"; }; $ssh->exit_session; $ssh->close_session; }

        What I mean is that you should let your exceptions go uncaught for upper levels where they can be handled properly. There is no reason to couple the exception catching with the cleanup code.