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

I am learning Perl, and I am trying to see what happens when I write some weird code. And I have some questions...
################################## sub AA{6} sub BB{{{3}}} sub L{AA+BB} # Now, here Perl thinks that I am # calling AA(+BB) so, instead of # adding 6+3, it simply returns 6 print "\nL=".L."\n"; print "\nL=".((AA) + BB) ."\n"; # Now I got it right. # Okay, I understand this. So far everything is clear. ################################## sub UNIQUE::print{print 'Hello World!'} UNIQUE->print(333); sub UNIQUE::print{ print "\nMuhahaha! @_ \n"; } UNIQUE->print(65.65.65.65); # Okay this is weird. # First of all, how does 65 become letter 'A' without using chr(65) ? # Secondly, Perl allows me to redefine my UNIQUE::print and now # this second definition overwrites the first one. # What happened to the first one??? # Why is my 'Hello World' never showing up at all? ################################## print "What on earth is this? >>> " . sub {5}; my $D = sub { print "What the Heck!"; }; # What am I doing here? # And why is this allowed in Perl? What's the point of # creating a noname sub? Okay, so if I wanted to, how # would I run my noname sub using the handle $D ? ################################## sub Red { sub LittleRed{'red'}; # sub within a sub LittleRed; # returns 'red' } print "\nPerl is getting confused here..." . Red; print "\n\n"; print LittleRed; # Wait. This is not supposed to work! # If I declare a sub within a sub, then the inner sub should # not be accessible from the outside. Is this right??? # I mean what's the point of declaring a sub within a sub # if it's the same as declaring it outside the sub? ################################### sub X{10} print "\nYES>".X; # This prints 10. Fine. sub Y{my$i=0;$i while($i++<10);}print"\nYES>".Y; # Now, why is this not printing 10?? # When the while loop ends, $i equals 10, so if I just # say "$i" then it should use that as a return value for # the sub. No? ########################### # Another question: Is there a way to # access previous return values? # Example: sub DDD { 0; 1; 2; 3; 4; 5; } print DDD; # Is it possible to do something like this # without using the = assignment operator?: # # sub DDD { # 4+4; # 5+(previous lines' result); # return previous line's result; # } # # So, DDD would return 13.

Replies are listed 'Best First'.
Re: Trying to understand Perl :-)
by Corion (Patriarch) on Jul 28, 2016 at 07:48 UTC

    You ask a lot of questions.

    sub UNIQUE::print{print 'Hello World!'} UNIQUE->print(333); sub UNIQUE::print{ print "\nMuhahaha! @_ \n"; } UNIQUE->print(65.65.65.65); # Okay this is weird.

    First of all, how does 65 become letter 'A' without using chr(65) ?

    You're creating a "version string" (see version). Version strings convert the numbers to characters.

    Secondly, Perl allows me to redefine my UNIQUE::print and now this second definition overwrites the first one. What happened to the first one???

    Perl executes your code in two phases. First it compiles your code. This is when your second declaration of UNIQUE::print overwrites your first declaration. This phase is commonly called the "compile" phase. Then, Perl runs the code. This is when all calls go to the (second) UNIQUE::print function and produce output.

    What on earth is this?

    sub {5};

    It's an anonymous subroutine, that is, a subroutine that you cannot call by name. You usually store it in a variable so that you can access it in other places of your program:

    my $five = sub { 5 }; print $five->();

    Anonymous subroutines are what makes map and grep useful. Also see Higher Order Perl for a good introduction where anonymous subroutines come in handy.

    sub Red { sub LittleRed{'red'}; # sub within a sub LittleRed; # returns 'red' } print "\nPerl is getting confused here..." . Red; print "\n\n"; print LittleRed;
    Wait. This is not supposed to work! If I declare a sub within a sub, then the inner sub should not be accessible from the outside. Is this right??? I mean what's the point of declaring a sub within a sub if it's the same as declaring it outside the sub?

    Declaring named subroutines within other named subroutines usually is an error. The visibility of subroutine names is global (except for lexical named subroutines, but these are experimental). Declaring nested named subroutines often leads to interesting problems which most often are shown by warnings as Variable %s will not stay shared.

    sub Y{ my$i=0; $i while($i++<10); } print"\nYES>".Y;
    Now, why is this not printing 10?? When the while loop ends, $i equals 10, so if I just say "$i" then it should use that as a return value for the sub. No?

    No. $i is not the expression returned from the last statement. A subroutine evaluates to the value of its last statement.

    Is there a way to access previous return values? Example:
    sub DDD { 0; 1; 2; 3; 4; 5; } print DDD;

    Yes. Use a comma instead of a semicolon (that is, return a list):

    sub DDD { 0, 1, 2, 3, 4, 5, }
      This is great! Thank you so much for your replies! They were very helpful. Okay, so a little clarification:
      sub ccc{65} print "\n" . ccc.ccc.ccc.ccc; # this evaluates to numbers print "\n" . 65.65.65.65.65; # this evaluates to letters # Ok. It's a little weird, but it is what it is. my $A = sub { print "\nWELCOME! :-) (@_)\n"; 1 }; my $B = sub { print "\nGO AWAY! >:( (@_)\n"; 2 }; my $X = time % 2 ? $A : $B; print $X->(77); $A = 0; $B = 0; $X = 0; # So, if I create anonymous subs, # I can later simply "erase" them? # This is great. # # But now, what happens to my anonymous subroutines? # Do they simply disappear or stay in memory somewhere? print "\n" . __PACKAGE__; print "\n" . __FILE__; print "\n" . __LINE__; print "\n\n"; #sub MY{ my $K = __SUB__; } # Why is this giving me an error? #MY; sub P{(6,7,8)} # returns an array print "\n".(P)[0]; print "\n".(P)[1]; print "\n".(P)[2]; # Makes sense.

        Hi harangzsolt33,

        sub ccc{65} print "\n" . ccc.ccc.ccc.ccc; # this evaluates to numbers print "\n" . 65.65.65.65.65; # this evaluates to letters # Ok. It's a little weird, but it is what it is.

        Well, Perl can tell the difference (on the side, a fun read), and if you know what v-strings are so can you :-) Note that whitespace is significant so that Perl can tell the difference between a v-string and numbers joined with the concat operator ".": print 65 . 65 . 65 . 65; prints "65656565".

        But now, what happens to my anonymous subroutines? Do they simply disappear or stay in memory somewhere?

        I'm not an expert on the internals but I believe they are subject to Perl's normal memory management, i.e. when the last reference to an anonymous sub goes away it is garbage-collected (the memory it used can be reclaimed by Perl). You normally don't need to worry about this, all you need to think about is that when you want a value to go away you make sure to discard all references to it, and that there are no circular references.

        sub MY{ my $K = __SUB__; } # Why is this giving me an error?

        See __SUB__: "This token is only available under use v5.16 or the current_sub feature. See feature."

        sub P{(6,7,8)} # returns an array

        This may seem nitpicky, but it's a common pitfall: that's not an array, that's a list. Note that return, including the implicit return value, passes along the context that the sub was called in. Your sub P, when called in list context (for example, when its return value is assigned to an array), will return the three values 6,7,8, and you won't be able to tell the difference between it and a sub Q { my @a = (6,7,8); @a } called in list context.

        However, you will be able to tell the difference when you write my $x = P; my $y = Q;: $x will contain 8 (the last value from the list), and $y will contain 3 (the number of items in the array)*. The reason is that sub P being called in scalar context causes its return value to be evaluated in scalar context, and the Comma Operator in scalar context "evaluates its left argument, throws that value away, then evaluates its right argument and returns that value." In sub Q, the return value @a evaluated in scalar context returns the number of elements of the array, the normal behavior of an array in scalar context.

        * By the way, a debugging tip: don't test code like this with arrays that contain numbers; use strings instead. You wouldn't have been able to tell the difference between $x and $y if the returned list had been (1,2,3).

        Hope this helps,
        -- Hauke D

        Please put your text in between <p>...</p> tags, and your code in between <code>...</code> tags. Writing your questions as stream-of-consciousness comments makes your post very unpleasant to read to me.

        Perl manages all memory through reference counting, so you can release most memory by not holding any reference to it anymore.

        If your question is "Why is this giving me an error", you will find it usually helps us help you much better if you explicitly show the verbatim error that Perl shows.

Re: Trying to understand Perl :-)
by haukex (Archbishop) on Jul 28, 2016 at 11:07 UTC

    Hi harangzsolt33,

    Just to mention a few more small things in addition to Corion's excellent post.

    print "\nL=".((AA) + BB) ."\n";

    An alternate way to tell Perl that the call to AA should take no arguments (instead of taking the return value of the call to BB) is (AA() + BB()).

    # sub DDD { # 4+4; # 5+(previous lines' result); # return previous line's result; # }

    In the first case, no, you'd need to write 5 + (4+4); or my $v = 4+4; 5+$v;.

    In the second case, from perlsub: "If no return is found and if the last statement is an expression, its value is returned." So all you need to write is sub foo { my $v = 4+4; 5+$v; } and foo will return 5+$v.

    perlsub also goes on to explain why your sub Y doesn't return the value of $i: "If the last statement is a loop control structure like a foreach or a while, the returned value is unspecified." It's easily achievable though: sub Y { my $i=0; $i while($i++<10); $i }

    And some more info on version strings: Version Strings

    Hope this helps,
    -- Hauke D

Re: Trying to understand Perl :-)
by Eily (Monsignor) on Jul 28, 2016 at 11:52 UTC

    ++ on the previous answers.

    Since you seem to be trying to dive a bit further into perl subs, your last question may be answered using Prototypes. Especially, the _ prototype which takes the default variable $_ as a parameter if none is provided. This only works for functions though, not operators. If I use say (same as print except \n is automatically appended) which prints $_ if no argument is provided :

    use v5.20; # use warnings and strict. Makes "say" available sub add( $ _ ) # Two scalars, the second is $_ if not provided { $_ = $_[0] + $_[1]; } sub ans { $_ } $_ = 7 and say; add 4, 5 and say; # prints 9 add 2 and say; # prints 11 add -4 and say "The answer is: ", ans; # prints 7
    With operators instead of functions, the best you can do in perl 5 is $_ = 4+4; $_ += 5;

Re: Trying to understand Perl :-)
by Anonymous Monk on Jul 28, 2016 at 06:51 UTC