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

what are the pros and cons to doing the following in any size script..?
#!/usr/bin/perl -w use strict; &a; sub a{ print "enter a number: "; chomp(my $a=<STDIN>); if ($a=~/[^\d]+/){ print "not a number!"; &a; } else { print "You typed: $a\n"; &a; } }
VS
#!/usr/bin/perl -w use strict; &a; sub a{ ASK: print "enter a number: "; chomp(my $a=<STDIN>); if ($a=~/[^\d]/){ print "not a number!\n"; goto ASK; } else { print "you entered: $a\n"; goto ASK; } }

Replies are listed 'Best First'.
Re: subroutine recurse vs goto LABEL
by chromatic (Archbishop) on Sep 14, 2001 at 22:42 UTC
    In the recursive example, if a malicious user provides sufficient amounts of bad input, Perl may kill your program with a "deep recursion" message. (The number 4000 comes to mind as the recursion limit, but I'd have to check.)

    In the goto example, you've basically written a while loop, which is how most people would do it.

    I'd remove the duplicate code from the end of each if/else statement, and write it as such:

    #!/usr/bin/perl -w use strict; # &subname can have unpleasant side effects a(); sub a { my $a; while (lc($a) ne 'q') { chomp($a = <STDIN>); last unless $a; if ($a =~ /\D/) { print "Not an integer!\n"; } else { print "You typed: ->$a<-\n"; } } }
    There's more than one way to do it.
Re (tilly) 1: subroutine recurse vs goto LABEL
by tilly (Archbishop) on Sep 14, 2001 at 23:06 UTC
    This is an argument that erupted in 1968 with Go To Considered Harmful and anyone in the last 20 years who has any awareness of program maintainability etc will tell you that the goto opponents won.

    Do not use goto as a general purpose control device. Learn to think in terms of structured control statements like standard looping structures, function calls, etc. The remaining uses which are generally accepted for goto in languages like C are filled in Perl by loop control statements like next, last, and redo. The remaining uses of goto in Perl which I consider appropriate involve deep voodoo. That is essentially, "If you don't know, then don't ask. You won't need to be doing it."

      So use a block and redo instead of goto for tail-end recursion elimination, if the compiler doesn't just do it for you. In this case, a "while there is still more to work on" loop is clearly correct.
Re: subroutine recurse vs goto LABEL
by patgas (Friar) on Sep 14, 2001 at 22:39 UTC

    Using a recursive function will always eat up more memory as you go, especially since your functions never stop or return anything. I suppose out your two examples, the second one is better, just because it's not recursive. Not that you asked, but I think you could write it more clearly and elegantly like this:

    #!/usr/bin/perl -w use strict; while ( <STDIN> ) { chomp(); if ( /^\d+$/ ) { print "You entered: $_\n"; } else { print "Not a number!\n"; } }

    "We're experiencing some Godzilla-related turbulence..."

Re: subroutine recurse vs goto LABEL
by derby (Abbot) on Sep 15, 2001 at 00:22 UTC
    AM,

    There are two rules to when you should use recursion (or actually if you can't fullfill these rules don't use recursion)

    Base Case: there must be at least one case where recursion is not called.

    Winnowing: each call in the recursion should be working on a subset of the data towards the base case.

    There are some other auxillary things to think about (memory consumption, namespace clashing, etc) and I remember reading somewhere that all recursive routines could and should be solved iteratively but sometimes recursion is damn fun and it amazes and annoys your coworkers.

    So looking at your code, you do have a base class - that read is going to end sometime, right? But, you're really not winnowing the data - your just moving through it sequentially.

    -derby

Re: subroutine recurse vs goto LABEL
by herveus (Prior) on Sep 14, 2001 at 23:57 UTC
    Howdy!

    In short, "no".

    More clearly, the question poses a false dilemma. Neither A nor B are good choices to perform the function they do. patgas offered a much clearer option C.

    The task being performed is not inherently recursive. Both versions obscure the essential core of the code. What is the problem being solved here?

    yours,
    Michael