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

After gaining much perl wisdom by just reading, now i have to ask a question myself.

I have a small skript which is executing subs in wrong order. Although i have found out, that i was missing a semicolon, i do not understand, WHY the execution order is altered without this semicolon.

And hence my question is: Why?

The code:
#!/usr/bin/perl use strict; use warnings; sub sub_A { print "sub_A\n"; } sub sub_B { print "sub_B\n"; } sub_A sub_B;

produces this output:

sub_B sub_A

After I add the missing semicolon after sub_A the output changes to the expected

sub_A sub_B

Replies are listed 'Best First'.
Re: sub execution order aka missing semicolon after sub call
by choroba (Cardinal) on Apr 06, 2016 at 15:30 UTC
    That's because without the semicolon, Perl understands the code as

    sub_A(sub_B());

    as you can easily verify with B::Deparse:

    $ perl -MO=Deparse,-p ~/1.pl sub sub_A { use warnings; use strict; print("sub_A\n"); } sub sub_B { use warnings; use strict; print("sub_B\n"); } use warnings; use strict; sub_A(sub_B());

    My advice is you should get into the habit of always using parentheses for function calls.

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,

      Thanks to all repliers.

      The idea with the habit of adding () after all sub-calls is indeed a very good idea.

        The idea with the habit of adding () after all sub-calls is indeed a very good idea.

        There is a special case where the use of parentheses is not appropriate. If you call subB from within subA using the syntax &subB with no parentheses then the argument list of subA will be passed to subB. See this node for an example.

        The subroutine doesn't actually have to be called from within another subroutine; it is the content of @_ that matters, as demonstrated by the following code.

        $ perl -Mstrict -Mwarnings -E ' @_ = @ARGV; ∑ sub sum { my $sum; $sum += $_ for @_; say $sum; }' 1 2 3 4 5 15 $

        I hope this is of interest.

        Cheers,

        JohnGG

Re: sub execution order aka missing semicolon after sub call
by haukex (Archbishop) on Apr 06, 2016 at 15:30 UTC

    Hi jmaas,

    Because in Perl parentheses are often optional, sub_A sub_B; means sub_A(sub_B()); (no matter if it's split on two lines), i.e. the return value of a call to sub_B() is being used as the argument(s) to sub_A(), which means sub_B() has to be called first. B::Deparse can show you this (edited slightly for brevity):

    $ perl -MO=Deparse,-p -e 'sub a {} sub b {} a; b;' sub a { } sub b { } a(); b(); $ perl -MO=Deparse,-p -e 'sub a {} sub b {} a b;' sub a { } sub b { } a(b());

    Hope this helps,
    -- Hauke D

Re: sub execution order aka missing semicolon after sub call
by davido (Cardinal) on Apr 06, 2016 at 15:30 UTC

    In your example code, Perl is seeing sub_B as the parameter to sub_A. Since the sub declarations came before the calls, parens are not needed as compiler clues, so it's perfectly legitimate syntax. Almost exactly the same as sub_A(sub_B()).

    So for sub_A to be called, sub_B must first be called so that its return value can be passed as the parameter to sub_A.


    Dave