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

Hey there!
I am a newbie to Perl and programming in general, :)

I hope I'll have your support in my journey to learn Perl from internet sources like tutorials and articles.

I came across this article (i'm very very inexperienced right now, its kinda difficult to decipher the good from the bad, so kindly bear with me here).

I says and I quote here:
"NOTE: In C++ there are cases where the calling code can "reach into" the function via the returned pointer or reference. This is appearantly not true of passed back scalars. Check out this code: "

My questions are:

  1. What does he mean by: reach into the calling code? a small snippet of some C/C++ code would be welcome!
  2. Is this a reference to the subrouitine:
    $ref = \&getGlobalName();
  3. Is the author saying that Perl has this ability to *reach into code*as well? If the answer is yes, then, can you please explain the elucidation that the author has used to explain the same and why Clinton is printed and not Gore as intended?
Thanks in advance for your time.

edited: Thu Jul 24 01:15:31 2003 by jeffa - code tags, formatting

Replies are listed 'Best First'.
Re: Reference to a function
by BrowserUk (Patriarch) on Jul 24, 2003 at 02:10 UTC

    The problem is that the author of the article to which you refer is slightly confused himself. He offers this code and explanation:

    The reason that

    $$ref = "Gore";

    doesn't appear to change anything, is because the author is confused about what he is taking a reference to when he does

    $ref = \&getGlobalName();

    He appears to think that this would give him reference to $GlobalName, whereas in fact it gives him a reference to a copy of $GlobalName! And when he assigns through that reference, he is modifying the copy, not the original. This can be seen clearly if you add a couple of lines to his code.

    As you can see, the function is returning a copy of $GlobalName, And the calling code takes a reference to this copy. It then modifies the copy indirectly through the reference, but goes on to print out the value of the original, by calling the function again and getting another copy. The first copy still exists and has been modified but was simply never being used.

    To achieve what the author apparently thought he was trying to do, the subroutine would need to return a reference to the original variable.

    As you can see, when the new function is called, it returns a reference to $GlobalName, and when you assign via this reference, you modify that (original) variable. Then when you call the original getGlobalName() function, the second time, it does return (a copy of) the modifed value.

    Of course, there is no need to have two functions.

    The syntax in the print statements has become slightly more complex, but it demonstrates the point. And this can be simplifed further as once you have the reference, there is no longer any need to call the function to access the variable.

    Overall, the authors statement about "reaching into a subroutine" is extremely confusing (not to say inaccurate:), and on the strength of that and several other bits I read in the section on subroutines, I couldn't recommend the material, though I have to say from my quick scan that he does seemed to have expended considerable effort on his content. Unfortunately, he seems to be suffering from a few misconseptions which spoil his efforts.

    If your looking for good material to help you get started with perl, the material on this site is seen and reviewed by a large number of experienced and eagle-eyed people. Mistakes and misconceptions are not allowed to persist for more than a few minutes around here (as I know from (too frequent) experience:)

    Rather than re-list all the good materials, I'll just recommend you read and following the links in this recent node by PodMaster. If you follow all those links and read the material therein, you'll get a very good start on learning perl.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller

Re: Reference to a function
by Zaxo (Archbishop) on Jul 24, 2003 at 00:52 UTC

    You should omit the parentheses, they try to call the sub before the reference is made. my $cref = \&getGlobalName;

    I'm unclear whether you're asking about C scoping rules for variables outside a function definition's scope, operations on a reference passed as an argument, or for external access to a function's internal variables. I think you mean the latter.

    In C/C++ you can safely "reach in" only for malloc'd (or new'd) store. A popular error is to return a reference to some auto variable within a function's definition block. By contrast, it is perfectly alright to return a reference to a lexical in perl. Reference counting keeps the value alive,

    sub foo { my @stuff = @_; # do stuff to @stuff return \@stuff; }

    After Compline,
    Zaxo

Re: Reference to a function
by Cody Pendant (Prior) on Jul 24, 2003 at 01:55 UTC
    I would be very wary of that article.

    It's written by someone who thinks the language is called PERL, it's out of date, and it's just simply confused as far as I can see.

    I'll let other monks comment but here's an excerpt pretty much at random.

    In computer science, there are two methods of passing arguments to a subroutine:

    • By value
    • By reference
    When passing by value, the language makes a copy of the argument, and all access inside the subroutine is to that copy. Therefore, changes made inside the subroutine do not effect the calling routine. Such arguments cannot be used as output from the subroutine. The preferred method of outputting from a subroutine is via the return value. Unfortunately, the PERL language doesn't support it. Instead, the programmer must explicitly make the copy inside the subroutine.

    In general, I believe it's best to use arguments as input-only.

    When passing by reference, the language makes the argument's exact variable available inside the subroutine, so any changes the subroutine makes to the argument affect the arguments value in the calling procedure (after the subroutine call, of course). This tends to reduce encapsulation, as there's no way of telling in the calling routine that the called routine changed it. Passing by reference harkens back to the days of global values, and in general creates less robust code.

    All arguments in PERL are passed by reference! If the programmer wishes to make a copy of the argument to simulate passing by value (and I believe in most cases he should), he must explicitly make the copy in the subroutine and not otherwise access the original arguments.

    And his notes when telling people how to deferences hashes say:

    sub dohash    {    my(%hash) = ("president"=>"Clinton",                 "vice president" => "Gore",                 "intern" => "Lewinsky");    my($ref) = \%hash;    # NOTE: Can't put %{ref} inside doublequotes!!! Doesn't work!!!    # Prints "internLewinskyvice presidentGorepresidentClinton".    # NOTE: Hash elements might print in any order!    print %{$ref}; print "\n";    # NOTE: OK to put ${$ref}{} in doublequotes.    # NOTE: Prints "Gore".    print "${$ref}{'vice president'}\n";    }


    ($_='kkvvttuubbooppuuiiffssqqffssmmiibbddllffss') =~y~b-v~a-z~s; print
      In computer science, there are two methods of passing arguments to a subroutine:

      Three, counting pass by name.

      See "Programming Language Pragmatics"
      Language features that most designers now believe were mistakes, at least in part because of implementation difficulties:
      * by-name parameters in Algol 60: Section 8.3.1 (Call By Name)

      The argument gets evaluated each time it is used in the subroutine.

        There's also call-by-need, which is basically just call-by-name with cached lazy evaluation. Basically, turn all your parameters into thunks (closure of no arguments) so they don't get evaluated when the method is invoked, and then evaluate them once and only once if they are referenced in the method.

        This post made for full-on nitpicking compliance :).
        Allen
Re: Reference to a function
by flounder99 (Friar) on Jul 24, 2003 at 12:05 UTC
    I think what the author was trying to show was that with C your pointers are real pointers to memory and once a variable is set up in a function its memory is fixed. If you fiddle with a pointer to it you will change it. Here is an example:
    int *mysub (); main() { int* x; x = mysub(); printf("in main x = %d\n", *x); *x = 5; x = mysub(); } int *mysub () { int z; printf("in sub z = %d\n", z); z = 3; return &z; }
    Compiling gives a warning but it still compiles.
    $ make temp gcc temp.c -o temp temp.c: In function `mysub': temp.c:13: warning: function returns address of local variable
    running it gives you:
    $ temp in sub z = 0 in main x = 3 in sub z = 5
    as you can see main "reached into" mysub and changed z. There is no equivalent way to "reach into" a perl function and fiddle with its my variables
    use strict; my $x; $x = &mysub; printf "in main \$x = %d\n", $$x; $$x = 5; $x = &mysub; sub mysub () { my $z; printf "in sub \$z = %d\n", $z; $z = 3; return \$z; }
    outputs:
    $ perl temp.pl in sub $z = 0 in main $x = 3 in sub $z = 0
    as you can see the main program could not "reach in" and change the value of $z in mysub even though you dereferenced the reference it returned. The my $z in mysub creates a new variable every time and does not just reference a fixed memory location as in C.

    Before an expert points it out:

    I know, I know, the memory locations may change in C depending on hardware, OS, etc. but I am trying just to give and example of things that are possible in C, not necessarily good programming practice.

    Update -- I noticed that if you make z static in mysub

    int *mysub () { static int z; ...
    the compiler (gcc in my case) will not emit a warning but the output of the program is the same.

    --

    flounder

Re: Reference to a function
by jonadab (Parson) on Jul 24, 2003 at 13:21 UTC

    In general, when learning Perl, you can safely ignore any literature that spends a lot of time discussing C or C++ and comparing Perl to them. Perl is nothing like either of these languages. (This is a good thing.)


    $;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}} split//,".rekcah lreP rehtona tsuJ";$\=$ ;->();print$/
      I disagree. There are a lot of C programmers that are given the task of writing/maintaining perl scripts. Perl references are in some ways like C pointers but in other ways very different. Expaining the subtleties can be very valuable. They may be confusing to a programming newbie but they can sure help someone who is well versed in C. One of the best ways to learn something is to compare/contrast it with something you know well.

      --

      flounder

        There are a lot of C programmers that are given the task of writing/maintaining perl scripts.

        They should treat Perl as a completely new language, just as they would lisp, and read introductory materiel on it.

        Perl references are in some ways like C pointers but in other ways very different. Expaining the subtleties can be very valuable.

        This is true, and even the Camel book does explain the differences between pointers and references. However, the OP was talking about an article that described how a specific problem was solved in C and layed out a very specific solution using pointers. Trying to apply an article like that to Perl is not a useful approach. It's one thing to read how Perl scalars are different from C integers or strings, and something else again to copy a C implemention of an algoritm for parsing numbers out of strings and try to adapt it to Perl. The former is useful; the latter is like applying knowlege of bicycle riding when flying an aircraft.


        $;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}} split//,".rekcah lreP rehtona tsuJ";$\=$ ;->();print$/
Re: Reference to a function
by Anonymous Monk on Jul 25, 2003 at 21:44 UTC
    I'm somewhat of a newbie myself (using Perl for a year or so). You can make it print Gore easily. I don't know what he's talking about (and neither does he). Check this out:
    ###His code $GlobalName = "Clinton"; sub getGlobalName { return($GlobalName); } print "Before: " . &getGlobalName() . "\n"; $ref = \&getGlobalName(); $$ref = "Gore"; print "After: " . &getGlobalName() . "\n";
    #All print statements printed "Clinton"
    ###His code improved $GlobalName = "Clinton"; sub getGlobalName { return($GlobalName); } print "Before: " . &getGlobalName() . "\n"; $GlobalName = "Gore"; print "After: " . &getGlobalName() . "\n";
    #Prints "Clinton" then "Gore" What he did was way off. He created a reference hard reference with:
    $ref = \&getGlobalName();
    If you were to:
    print "$ref \n";
    It would look something like:
    CODE(0x1a45934)
    What he said was the same as:
    ${CODE(0x1a45934)} = "Gore"
    or creating a soft reference.