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

Dear Monks

I have made a subroutine that works properly, but when I use "or die", then it dies after the first call ! When I do not use "or die" then the all results are printed. Could you explain ? Thanks

Here is the structure of the code

my $element; foreach $element(@Elements){ &process($element) or die; } sub process{ chdir("$path_to_the_data_directory")or die; my $outfile; #the $outfile name depends on $reg; open my $OUTFILE, q{>}, $outfile; my $infile = "data.txt"; open my $INFILE, q{<}, $infile; while (my $line = <$INFILE>){ # several operations which produce "$results" print $OUTFILE "$results\n"; } close $OUTFILE; chdir("$path_to_the_script_directory") or die; }

Replies are listed 'Best First'.
Re: &process or die
by moritz (Cardinal) on Apr 18, 2008 at 12:49 UTC
    Your sub process returns 0 (or another false value), so the "or die" is executed.

      Thanks moritz

      Now I understand, because my subroutine does NOT return a number. It makes mathematical operations on files and prints results but there is NOT a return so it is normal "die" is executed !

        my subroutine does NOT return a number.
        That is not true, according to the documentation for return, and as others in this thread have already pointed out:
        (Note that in the absence of an explicit "return", a subroutine, eval, or do FILE will automatically return the value of the last expression evaluated.)
        This is why moritz correctly pointed out that your sub is indeed returning a value, and it even might be numeric (0).

        Consider the following contrived example:

        #!/usr/bin/env perl use warnings; use strict; my $result; $result = foo(); print "result=$result\n"; $result = bar(); print "result=$result\n"; sub foo {print "foo: "} sub bar {print "bar: "; chdir '/nodir'}

        This prints:

        foo: result=1 bar: result=0

        sub "foo" returns the result of the successful print command, and sub "bar" returns the result of the unsuccessful chdir command.

Re: &process or die
by mscharrer (Hermit) on Apr 18, 2008 at 12:57 UTC
    process() is returning a boolean false value so the part after 'or' is executed. Your code means: "process all elements but die at the first failing element". That's maybe not what you want.

    Also your function doesn't use a 'return' statement so it returns the return value of the last statement which is 'close()' in this case. Close seems to return false which might be caused be a failing open() in the first place. You can't close a file which you couldn't open.

    Do you use use strict; use warnings; ?? If not put it in and look for correlated warnings.

      Dear mscharrer Thanks a lot for your help

      I have taken into consideration what you have said. In fact the last line of my subroutine is:

      chdir("$path_to_the_script_directory") or die;

      And I do not have any errors (when I do not use "or die" for process() )

      But in my operations of process(), I have used :

      while (my $line = <$INFILE>){

      And when I want to print $_ after the loop, I have :

      Use of uninitialized value in concatenation (.) or string at
        And when I want to print $_ after the loop, I have

        $_ and $line are different variables. The contents of one may or may not reflect the contents of the other.

Re: &process or die
by FunkyMonk (Bishop) on Apr 18, 2008 at 13:05 UTC
    In Perl, or is a shortcircuiting operator. That is, the first operand is evaluated, and if-and-only-if it is false, the second is evaluated. &process($element) or die will call your subroutine and if it returned false, the script will die.

    So, what does the subroutine return? Without an explicit return, subroutines return the value of the last statement, in this case, the return of close $OUTFILE. close returns a false value on error, so your close failed.


    Unless I state otherwise, my code all runs with strict and warnings
Re: &process or die
by Fletch (Bishop) on Apr 18, 2008 at 13:43 UTC

    And a style nit tangental to the die-ing: 99% of the time you don't want to use & when calling subs because it alters how the call is made (see perlsub for the gory details). Calling process( $element ) will work just fine and you'll be glad you didn't get into a bad habit and have to go chasing down why that line &spoo or warn "Zoikes!\n" is getting passed arguments.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

Re: &process or die
by rowdog (Curate) on Apr 18, 2008 at 20:36 UTC
    My gut feeling is that the open call is failing and you're seeing the result in a failed close that returns to your loop and dies. Check the return of open...

    open my $OUTFILE, q{>}, $outfile or die "failed to open $outfile: $!";

    On another note, you can use the path and skip the chdir calls. e.g.

    my $OUTFILE, q{>}, "$path_to_the_data_directory/$outfile" or die "failed to open $path_to_the_data_directory/$outfile: $!";
Re: &process or die
by Anonymous Monk on Apr 18, 2008 at 14:11 UTC
    I'm astonished that you say your subroutine works properly without the die, because it shouldn't.

    Your subroutine should start with

    sub process{ my $outfile= shift;