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

salva: There are several ways to do it, but IMO, the easiest and most straight forward is as follows: goto end

Um, two subroutines :)

sub foo { ... my $rc = fooFoo($ssh); $ssh->exit_session(); $ssh->close_session; return $rc; } sub fooFoo { my ($ssh) = @_; if ( !$ssh->start_session($ssh_host) ) { print "ERROR connecting to $ssh_host\n"; return 1; } my ( $ret, $err ) = $ssh->execute( 'command1', 'expect1' ); if ( $err || $ret =~ /Unknown command:/m ) { return 2; } my ( $ret, $err ) = $ssh->execute( 'command2', 'expect2' ); if ( $err || $ret =~ /Unknown command:/m ) { return 3; } return 0; }

Replies are listed 'Best First'.
Re^3: exiting a subroutine neatly (Throwable)
by Anonymous Monk on May 05, 2015 at 10:11 UTC
    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; }
      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

Re^3: exiting a subroutine neatly
by salva (Canon) on May 05, 2015 at 10:13 UTC
    Well, I still find my approach more straight forward.
      I use it in .bat files all the time :) but then thats the only choice in .bat files