in reply to Passing argument by reference (for a scalar)

I think, passing a string by reference makes sense when you work with extremely large strings. For example, if you were to store an entire image in raw uncompressed format in a string, then you better pass by reference lest you accidentally end up with copies in memory... Let's say you have a 4000x3000x24 image in memory. That's almost 40 megabytes. Now, if you read and write this string, you are better off if you pass by reference. Plus, you don't know who will run your script. Maybe someone will try to run it using an older Perl interpreter which does not have smart optimizations built into it. So, I think, it's safer when you're dealing with file contents or images or anything really big. Now, I've noticed that there is a slight toll in speed. Operations like substr($$REF, ...) are slightly slower than substr($STRING, ...) but it's negligible.
  • Comment on Re: Passing argument by reference (for a scalar)

Replies are listed 'Best First'.
Re^2: Passing argument by reference (for a scalar)
by ikegami (Patriarch) on Sep 09, 2024 at 03:35 UTC

    I think, passing a string by reference makes sense when you work with extremely large string

    Please read the earlier answers which show this completely wrong. Perl always passes by reference, so there's no reason to pass a reference.

    Note that COW has a chance of failing. (The scalar needs to "owned by Perl", and its string buffer must have space to accommodate the COW count.) But even if you want to give your argument names without relying on COW, you don't have to change your code to use references. Instead, you can replace

    my $x = shift;

    with

    use experimental qw( refaliasing declared_refs ); my \$x = \shift;

    or

    use Data::Alias qw( alias ); alias my $x = shift;

    or

    our $x; local *x = \shift;
      Perl always passes by reference

      Okay, but then why is it that as soon as I do my $STRING = shift; inside my sub, Perl's memory usage doubles (using TinyPerl 5.8 under Windows XP)?

      It seems like it may be passed by reference, but as soon as you grab that using shift() or just do my $MYSTRING = $_[0]; then viola! You have another copy of the string!

        using TinyPerl 5.8 under Windows XP

        Tinyperl is not fully perl: it doesn't even come with Devel::Peek, which has been core since 5.6, before tinyperl 5.8.0 was released. (I found this out when I vainly tried to use your own favorite pseudo-perl to run ikegami's example, and couldn't, because it didn't have that essential part of core.)

        When I use Strawberry Perl 5.8.8 (which comes with all of core), it gets essentially the same results that ikegami already showed: if you use the subroutine's argument directly, rather than making a copy of the string, then Perl doesn't copy the string.

        why is it that as soon as I do my $STRING = shift; inside my sub, Perl's memory usage doubles

        You do realize that you just essentially asked, "why is it that as soon as I make a copy of the string inside my sub, Perl makes a copy of the string?" Do you understand how silly it sounds when rephrased that way?

        Perl 5.8 doesn't have the fancy v5.20 Copy-on-Write ("COW") feature that ikegami mentioned (so the scalar of the copied version doesn't point to the same string buffer), but it does pass the subroutine arguments by reference (so the scalar is the same outside and inside of f($x) ). However, as soon as you make a copy of a string passed by reference, you no longer are using that reference, but a copy of the string -- hence, without COW, the memory goes up when you make the copy , but not when you called the sub . If, like ikegami, you stick to always using the $_[0] rather than creating a copy, it would not double your memory even in tinyperl.

        update: rephrased a few things, but essentially meaning has stayed the same

        update 2: too harsh in some of my wording, especially the struck out -- sorry.

        Same thing would happen if you did my $STRING = ${ +shift }; if you had passed a reference. If you don't want a copy, don't make a copy! (Also, don't use a 20 year old version of the language!) This was already all covered in detail. Including how what you claim happens hasn't been true for 10 years.