Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister

Re: Number of times I've used goto in Perl

by (anonymized user) (Curate)
on Mar 25, 2015 at 17:55 UTC ( #1121323=note: print w/replies, xml ) Need Help??

in reply to Number of times I've used goto in Perl

The problem one often faces is where at first sight standards and/or best practices conflict. In this case, there are at least three potentially conflicting factors that may need to be considered: 1) avoiding excessive nested blocks in terms of length and depth, 2) having a single point of return or exit from a routine or subroutine and 3) avoiding goto. Example:
sub fred { # meeting all three requirements:- my ($t, $u, $v, $w, $x, $y) = @_; somelogger( 5, "fred", "start of fred"); my $ok = method1($t); $ok &&= method2($u); my $pid = open my $ph, "/somewhere/program $v |"; my $output = ''; $ok &&= method3( <$ph>, \$output ); close $ph; waitpid $ph,0; # and so on for functionality using $w, $x and $y (in worst case s +cenario) # if goto were used to jump to the exit point the # label would have been here. if ($ok) { somelogger( 5, "fred", "fred completed successfully"); } else { somelogger( 5, "fred", "error during fred"); } return $ok; }
The point is that if goto were avoided using ifs, there would be one nesting level per error condition. Using &&= enables the code to cascade (without extra nested blocks) to the end whenever an error occurs. But many might consider the &&= too techy for the average programmer. Any thoughts, alternatives?

One world, one people

Replies are listed 'Best First'.
Re^2: Number of times I've used goto in Perl
by jdporter (Canon) on Mar 26, 2015 at 20:19 UTC
    3) avoiding goto

    Avoiding goto is not an end in itself (unless one is religious about it, taking "avoid goto" as a tenet of the faith); it is only, at best, a means to some other end.

Re^2: Number of times I've used goto in Perl
by ikegami (Pope) on May 06, 2018 at 08:10 UTC

    Seems like you are doing two tasks in here, which is why you're even thinking of goto.

Re^2: Number of times I've used goto in Perl
by AnomalousMonk (Bishop) on Mar 25, 2015 at 22:03 UTC
    ... &&= too techy ...

    A bit too techy and, for these old eyes, just plain difficult to see! I think I'd incline toward something like (all untested)

    sub fred { my ($t, $u, $v, $w, $x, $y) = @_; somelogger(5, "fred", "start of fred"); my $ok = 1; $ok = method1($t) if $ok; $ok = method2($u) if $ok; my $pid = open my $ph, "/somewhere/program $v |"; my $output = ''; $ok = method3(<$ph>, \$output) if $ok; close $ph; waitpid $ph,0; if ($ok) { somelogger(5, "fred", "fred completed successfully"); } else { somelogger(5, "fred", "error during fred"); } return $ok; }
    or maybe even (assuming the methods can be made to return error strings or the empty string for no error)
    sub fred { my ($t, $u, $v, $w, $x, $y) = @_; somelogger(5, "fred", "start of fred"); my $err; $err = method1($t) unless $err; $err = method2($u) unless $err; my $pid = open my $ph, "/somewhere/program $v |"; my $output = ''; $err = method3(<$ph>, \$output) unless $err; close $ph; waitpid $ph,0; if ($err) { somelogger(5, "fred", "error '$err' during fred"); } else { somelogger(5, "fred", "fred completed successfully"); } return $err; }

    Give a man a fish:  <%-(-(-(-<

Re^2: Number of times I've used goto in Perl (sub, return++)
by tye (Sage) on Mar 26, 2015 at 00:03 UTC
    1) avoiding excessive nested blocks in terms of length and depth, 2) having a single point of return or exit from a routine or subroutine and 3) avoiding goto.

    That's why Larry created subroutines.

    And (2) is just a stupid restriction. Adding extra returns is one of the most effect refactoring tools I found.

    - tye        

      ... subroutines ... extra returns ...

      I don't understand these points.

      Certainly using multiple returns and/or refactoring code into subroutines can, in general, be extremely useful for improving the readability/reliability/maintainability of code.

      But the particular code example presented in Re: Number of times I've used goto in Perl has a rather unusual structure. There are two interleaved streams of function calls and instructions:

      • optional functions that may be called only if no previous optional function failed;
      • required function calls and instructions that must all be called in order even if any previous optional function call has failed.

      Using multiple returns and/or refactoring into subroutines (or even (shudder) using nested if-elsif-else blocks or conditional goto statements), it would certainly be possible to replicate the control flow of the OPed code, but again, I can't see how it would be any improvement on (anonymized user)'s basic approach; indeed, it seems to me that it could only be much worse. Can you give an example of what you envision?

      Give a man a fish:  <%-(-(-(-<

        Yeah, I saw several things in that node. There was the topic of this thread (goto), the intro paragraph that said that this can conflict with 2 other things, and a prominent code comment suggesting that a label could be inserted if goto were used. And none of that seems to have anything to do (as far as I could figure out) with the alternating-&&= part of the code that you commented on. I agree that the &&= part of the code is interesting. I also fail to see where a goto would help any of the code shown.

        So I was only addressing the topic that matched the thread, the opening paragraph, and the prominent comment in the code.

        Perhaps it was actually desirable for the &&= short-circuiting to apply to all of the code so the better alternative was a lot of "goto failed if ! ...;" lines? That's my best guess, anyway.

        For such a case, the better approach I would do would be to change:

        sub do_lots_and_log { ... goto failed if ! method1(...); ... log("yay!"); return; failed: log("boo!"); }


        sub do_lots_and_log { if( do_lots(...) ) { log("yay!"); } else { log("boo!"); } } sub do_lots { ... method1(...) or return 0; ... return 1; }

        Sometimes "throw exception" is an even better solution than "early return", of course.

        - tye        

      Adding extra returns makes it much more time-consuming for someone who didn't write the code to figure out what the return value of a routine is or means. (It also means extra code if you're using any debugging tools to check assertions or track runtime with code that executes at the start and end of important routines. Which I always do in Perl, because Perl has so little typing.)

      In fact, about the only time I use goto is to goto the exit point of a routine. The necessary label will notify anyone looking at that code that there is some internal path directly to it.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1121323]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (6)
As of 2019-10-16 01:51 GMT
Find Nodes?
    Voting Booth?