Beefy Boxes and Bandwidth Generously Provided by pair Networks RobOMonk
go ahead... be a heretic
 
PerlMonks  

Is it possible to do pass by reference in Perl?

by Anonymous Monk
on Apr 03, 2000 at 21:06 UTC ( [id://6758]=perlquestion: print w/replies, xml ) Need Help??

This is an archived low-energy page for bots and other anonmyous visitors. Please sign up if you are a human and want to interact.

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

Is it possible to do pass by reference in Perl?

Originally posted as a Categorized Question.

  • Comment on Is it possible to do pass by reference in Perl?

Replies are listed 'Best First'.
Re: Is it possible to do pass by reference in Perl
by chromatic (Archbishop) on Apr 03, 2000 at 21:53 UTC
    Prepending a variable with a backslash (\) creates a reference:
    my $scalar = "this is a scalar"; my @array = qw( this is my array ); my %hash = ( 'this' => 'my', 'hash' => 'mine',); print_all(\$scalar, \@array, \%hash); sub print_all { my $scalar_ref = shift; my $arr_ref = shift; my $hash_ref = shift; print "Scalar: ", $$scalar_ref, "\n"; print "Array: ", join ' ', @$arr_ref, "\n"; print "Hash: ", each %$hash_ref, "\n"; }
    See perlman:perlref for the juicy details.
Re: Is it possible to do pass by reference in Perl
by btrott (Parson) on Apr 03, 2000 at 23:12 UTC
    ... And, as would follow from chromatic's answer, if you modify the references within a subroutine, you'll also modify the values those references point to, outside the subroutine.
    my $str = "foo"; print $str, "\n"; change(\$str); print $str, "\n"; sub change { my $ref = shift; $$ref = "bar"; }
Re: Is it possible to do pass by reference in Perl?
by ariels (Curate) on Sep 24, 2001 at 09:21 UTC
    *Only* scalars can be passed to a sub as parameters, and they can *only* be passed by reference. If you modify @_, the actual variable passed in gets modified! @_ is really a list of aliases to the argument list.

    Try it:

    sub foo { $_[0] = 17 } my $x=0; foo $x; print "$x\n"
    And foo @x does what you'd expect given the aliasing.

    Of course, the usual course of action is to copy them into my variables. Which is why it's perceived as call by value.

      It is only possible to pass scalars by reference to a sub.

      Parameters are passed by value in Perl. But we have an operator, the backslash, that returns reference to any variable (scalar or composite). So the net result is that we have a mechanism to pass parameter by reference.

      Admittedly, this not very clean, because the formal parameter is declared as a scalar even if it is a reference to a non scalar. I guess that was the point that tried to convey the sentence: It is only possible to pass scalars by reference to a sub.

      sub foo { my $a = shift; push @$a, "foobar"; } my @a = (); foo \@a; # passing a value that is a reference to @a print $a[1]; # prints "foobar"
      tilly messages me: another example of how to pass arrays by reference is by using prototypes. Unlike using \ in user code, that is transparent.. So Perl has call by reference after all (even if it was quite a late addition?).

      -- stefp

Re: Is it possible to do pass by reference in Perl?
by tilly (Archbishop) on Sep 24, 2001 at 12:12 UTC
    In addition to the answers above it is possible to pass arrays and hashes by reference without using a \. The way to do this is to define a function with a prototype as explained in perlsub.

    For a more complete explanation I can recommend FMTYEWTK About Prototypes, which says in detail what they are, where they are buggy, and the various design flaws that make them something to avoid on the whole.

Re: Is it possible to do pass by reference in Perl?
by Russ (Deacon) on Mar 05, 2002 at 14:32 UTC
    One might argue that Perl always does Pass-By-Reference, but protects us from ourselves.

    @_ holds the arguments passed to a subroutine, and it is common idiom to see something like:

    sub mySub{ my $Arg = shift; } sub mySub2{ my ($Arg) = @_; }
    Why is that? Why don't we just use the @_ array directly?

    First, there is the laudable goal of more readable code, which is sufficient reason, in itself, to rename variables away from cryptic things like $_[3]. But really, we copy values out of @_ because (from the man page) "its elements are aliases for the actual scalar parameters."

    In short, this means that if you modify an element of @_ in your subroutine, you are also modifying the original argument. This is almost never the expected behavior! Further, if the argument is not updatable (like a literal value, or a constant), your program will die with an error like "Modification of a read-only value attempted."

    Consider:

    sub test{ $_[0] = 'New Value'; } my $Var = 'Hi there'; print "$Var\n"; test ($Var); print "$Var\n";
    will print out:
    Hi there New Value
    So, yes, you can do pass-by-reference in Perl, even without backslashes; but it is almost always better (some would leave out the "almost" in this statement) to make your caller explicitly pass you a reference if you intend to modify a value.
Re: Is it possible to do pass by reference in Perl?
by RedDragon (Initiate) on May 18, 2002 at 04:49 UTC
    It is possible to pass by reference in perl. The argument list u get inside ur subroutine via @_ are implicit reference to values that were passed in from inside from outside.i.e. if u pass in a list of strings, inside the body of the sub,change those strings,then they will be modified outside the subroutine.
    sub ted { my($add,$sub,$mul) = @_; ... .. }
Re: Is it possible to do pass by reference in Perl?
by RedDragon (Initiate) on May 18, 2002 at 05:05 UTC
    It is possible to pass by reference in perl. The argument list u get inside ur subroutine via @_ are implicit reference to values that were passed in from inside from outside.i.e. if u pass in a list of strings, inside the body of the sub,change those strings,then they will be modified outside the subroutine.

    Originally posted as a Categorized Answer.

Re: Is it possible to do pass by reference in Perl?
by Anonymous Monk on Mar 08, 2004 at 01:17 UTC
    Programming SUCKS!!!!

    Originally posted as a Categorized Answer.

Re: Is it possible to do pass by reference in Perl?
by bradcathey (Prior) on May 18, 2004 at 21:31 UTC
    In fact, passing by reference is a must to preserve the values in separate data structures, even an array and scalar. For instance:
    my @array = qw ( 1 2 3 4 5 ); my $num = 6; &testsub ( @array, $num ); sub testsub { my ( @list, $single ) = @_; print @list; }
    will print:
    123456
    Passing those values via the @_ flattens all values into one long list. However:
    my @array = qw ( 1 2 3 4 5 ); my $num = 6; &testsub ( \@array, $num ); sub testsub { my ( $list, $single ) = @_; print @$list; }
    will print:
    12345
    where passing the array by ref will keep the values from all merging into the single list.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://6758]
help
Sections?
Information?
Find Nodes?
Leftovers?
    Notices?
    hippoepoptai's answer Re: how do I set a cookie and redirect was blessed by hippo!
    erzuuliAnonymous Monks are no longer allowed to use Super Search, due to an excessive use of this resource by robots.