Pass by reference question

Discussion in 'Perl Misc' started by grocery_stocker, Aug 13, 2007.

  1. If perl can pass stuff by reference, then why do you have to deference
    it. Like for example

    @tailings = popmany ( \@a, \@b, \@c, \@d );


    sub popmany {
    my $aref;
    my @retlist = ();
    foreach $aref ( @_ ) {
    push @retlist, pop @$aref;
    }
    return @retlist;
    }


    Wouldn't it be more accurate to say that perl passes the reference by
    value? I just find this sort of odd because in both Java (withc uses
    pass the reference by value) and C++ (which supports pass by
    reference), I never recall having to dereference a reference like what
    I have to in perl.
    grocery_stocker, Aug 13, 2007
    #1
    1. Advertising

  2. On Aug 12, 7:34 pm, Sherm Pendley <> wrote:
    > grocery_stocker <> writes:
    > > Wouldn't it be more accurate to say that perl passes the reference by
    > > value?

    >
    > Yes. So why did you say it passes by reference, when you already know a
    > more accurate way of saying it?
    >


    Because too my knowledge, ALL the perldocs and perl books say perl
    just passes the reference. I couldn't find anything in the perldocs
    that would hint that perl uses 'pass the reference by value'.
    grocery_stocker, Aug 13, 2007
    #2
    1. Advertising

  3. grocery_stocker <> wrote:
    > If perl can pass stuff by reference, then why do you have to deference
    > it.


    No, you can't. Perl only allows to pass scalars to functions and
    those are passed by value. The only thing that's a bit special
    in Perl is that if you e.g. have an argument that is an array it
    automatically gets converted into a list of scalars and the values
    of these scalars get passed to the subroutine. (Other languages
    have similar ways that may look strange at a first glance, e.g.
    in C and C++ if you use an array as the argument of a function
    it automatically gets converted into a pointer to the first
    element of the array and this value is passed to the function.)

    > Like for example


    > @tailings = popmany ( \@a, \@b, \@c, \@d );


    Sorry, but here you pass scalars to Perl whose values are
    references. This is not the same as "passing by reference".
    "Passing by reference" means that an argument automatically
    gets converted to a reference and that within the subroutine
    receiving it in all places the argument is also automatically
    dereferenced without you having to spell it out explicitely.

    Compare the these two C++ functions: that do the same thing:

    void foo_by_val( int* i ) {
    *i = 3;
    }

    void foo_by_ref( int& i ) {
    i = 3;
    }

    The first one you would have to call as

    int x;
    foo_by_val( &x );

    and the second as

    foo_by_ref( x );

    Perl only has an equivalent for the foo_by_val() function but
    not for foo_by_val().

    > sub popmany {
    > my $aref;
    > my @retlist = ();
    > foreach $aref ( @_ ) {
    > push @retlist, pop @$aref;
    > }
    > return @retlist;
    > }


    > Wouldn't it be more accurate to say that perl passes the reference by
    > value?


    It's redundant since Perl only passes by value. A reference is
    nothing than a scalar (basically what you would call a pointer
    in C or C++) and scalars, the only things you can pass to sub-
    routines, are always passed by values.

    > I just find this sort of odd because in both Java (withc uses
    > pass the reference by value) and C++ (which supports pass by
    > reference), I never recall having to dereference a reference like what
    > I have to in perl.


    You have to because Perl (like e.g. C but unlike Java or C++)
    simply doesn't do "pass by reference", just "pass by value".

    Regards, Jens
    --
    \ Jens Thoms Toerring ___
    \__________________________ http://toerring.de
    Jens Thoms Toerring, Aug 13, 2007
    #3
  4. Jens Thoms Toerring wrote:
    > grocery_stocker <> wrote:
    >
    >>If perl can pass stuff by reference, then why do you have to deference
    >>it.

    >
    >
    > No, you can't. Perl only allows to pass scalars to functions and
    > those are passed by value.


    Why, then, does the following script print "Bar"?

    sub f($) {
    $_[0] = 'Bar';
    }
    my $v = 'Foo';
    f($v);
    print "$v\n";

    Josef
    --
    These are my personal views and not those of Fujitsu Siemens Computers!
    Josef Möllers (Pinguinpfleger bei FSC)
    If failure had no penalty success would not be a prize (T. Pratchett)
    Company Details: http://www.fujitsu-siemens.com/imprint.html
    Josef Moellers, Aug 13, 2007
    #4
  5. Jens Thoms Toerring wrote:
    > grocery_stocker <> wrote:
    >
    >>If perl can pass stuff by reference, then why do you have to deference
    >>it.

    >
    >
    > No, you can't. Perl only allows to pass scalars to functions and
    > those are passed by value.


    Why, then, does the following script print "Bar"?

    sub f($) {
    $_[0] = 'Bar';
    }
    my $v = 'Foo';
    f($v);
    print "$v\n";

    And what does this script's error message tell us?

    sub f($) {
    $_[0] = 'Bar';
    }
    f('Foo');

    With all due respect,

    Josef
    --
    These are my personal views and not those of Fujitsu Siemens Computers!
    Josef Möllers (Pinguinpfleger bei FSC)
    If failure had no penalty success would not be a prize (T. Pratchett)
    Company Details: http://www.fujitsu-siemens.com/imprint.html
    Josef Moellers, Aug 13, 2007
    #5
  6. grocery_stocker

    -berlin.de Guest

    grocery_stocker <> wrote in comp.lang.perl.misc:
    > If perl can pass stuff by reference, then why do you have to deference
    > it. Like for example
    >
    > @tailings = popmany ( \@a, \@b, \@c, \@d );
    >
    >
    > sub popmany {
    > my $aref;
    > my @retlist = ();
    > foreach $aref ( @_ ) {
    > push @retlist, pop @$aref;
    > }
    > return @retlist;
    > }
    >
    >
    > Wouldn't it be more accurate to say that perl passes the reference by
    > value? I just find this sort of odd because in both Java (withc uses
    > pass the reference by value) and C++ (which supports pass by
    > reference), I never recall having to dereference a reference like what
    > I have to in perl.


    The perceived problem here is mostly due to ambiguous terminology.

    There is the common distinction of parameter passing "by value" vs "by
    reference". The first one means that all a subroutine ever gets to see
    is a copy of the parameter value whereas the second means the subroutine
    has access to the variable as it exists in the caller's context and can,
    for instance, change the value so that the change is visible to the
    caller.

    Perl subs implement "pass by reference" in this sense, since assigning
    to elements of @_ changes the value for the caller. This description
    went into the Perl documentation, and when Perl was young (before Perl
    5) this caused no problems because the term "reference" didn't have
    a Perl-specific meaning back then.

    That changed when Perl 5 introduced its own references (what you get
    by prefixing a variable with a backslash). These references are *not*
    what Perl uses to implement its "pass by reference", but an entirely
    distinct notion. In Perl terms, what is commonly called "pass by
    reference" might be called "pass by alias(ing)", but that term is not
    in general use and wouldn't be readily understood. So the documentation
    continues to use the commonly recognized term even after it has become
    ambiguous.

    Anno
    -berlin.de, Aug 13, 2007
    #6
  7. grocery_stocker wrote:
    > If perl can pass stuff by reference, then why do you have to deference
    > it. Like for example
    >
    > @tailings = popmany ( \@a, \@b, \@c, \@d );
    >
    >
    > sub popmany {
    > my $aref;
    > my @retlist = ();
    > foreach $aref ( @_ ) {
    > push @retlist, pop @$aref;
    > }
    > return @retlist;
    > }
    >
    >
    > Wouldn't it be more accurate to say that perl passes the reference by
    > value? I just find this sort of odd because in both Java (withc uses
    > pass the reference by value) and C++ (which supports pass by
    > reference), I never recall having to dereference a reference like what
    > I have to in perl.
    >


    Perl passes variables by reference and dereferences them automagically.
    If you explicitly pass a reference ('\@a'), you'll have to dereference
    it explicitly.
    I.e. in your example, popmany is passed four references to references to
    arrays.

    Josef
    --
    These are my personal views and not those of Fujitsu Siemens Computers!
    Josef Möllers (Pinguinpfleger bei FSC)
    If failure had no penalty success would not be a prize (T. Pratchett)
    Company Details: http://www.fujitsu-siemens.com/imprint.html
    Josef Moellers, Aug 13, 2007
    #7
  8. Josef Moellers <> wrote:
    > Jens Thoms Toerring wrote:
    > > grocery_stocker <> wrote:
    > >
    > >>If perl can pass stuff by reference, then why do you have to deference
    > >>it.

    > >
    > > No, you can't. Perl only allows to pass scalars to functions and
    > > those are passed by value.


    > Why, then, does the following script print "Bar"?


    > sub f($) {
    > $_[0] = 'Bar';
    > }
    > my $v = 'Foo';
    > f($v);
    > print "$v\n";


    > And what does this script's error message tell us?


    > sub f($) {
    > $_[0] = 'Bar';
    > }
    > f('Foo');


    It tells me that I obviously I was writing BS, at least when I
    didn't mention that using prototypes changes the picture.

    Ok, to the OP: you could write your function e.g. as

    sub popmany(\@;\@;\@;\@) {
    return map { pop @$_ } @_;
    }

    and then call it as

    @tailings = popmany @a, @b, @c, @d;

    using the possibility to "pass by reference" when using prototypes.
    But please note that this only will work with up to four arrays,
    so the function would be better named pop_up_to_four() or something
    like that.

    But my personal preference is to avoid prototypes except for the
    very purpose they were introduced for, mimiking the behaviour of
    built-in functions like push or pop. You still have to use the
    dereference syntax for arrays and hashes within the subroutine
    since what arrives within the subroutine are still scalars. And
    be wary of modifying elements of @_ unless you understand fully
    what to expect (I find it a bit weird). And, finally, prototypes
    don't influence method calls, only "normal" functions.

    At least don't assume that prototypes play a similar role to
    those in other languages like C, C++, Java etc., they don't.
    They aren't meant for compile time type checking.

    Regards, Jens
    --
    \ Jens Thoms Toerring ___
    \__________________________ http://toerring.de
    Jens Thoms Toerring, Aug 13, 2007
    #8
  9. grocery_stocker

    -berlin.de Guest

    grocery_stocker <> wrote in comp.lang.perl.misc:
    > If perl can pass stuff by reference, then why do you have to deference
    > it. Like for example
    >
    > @tailings = popmany ( \@a, \@b, \@c, \@d );
    >
    >
    > sub popmany {
    > my $aref;
    > my @retlist = ();
    > foreach $aref ( @_ ) {
    > push @retlist, pop @$aref;
    > }
    > return @retlist;
    > }


    On an unrelated note (unrelated to the question, that is), popmany()
    can be written more compact as

    sub popmany { map pop @$_, @_ }

    Anno
    -berlin.de, Aug 13, 2007
    #9
  10. grocery_stocker

    Guest

    grocery_stocker <> wrote:
    > If perl can pass stuff by reference, then why do you have to deference
    > it. Like for example
    >
    > @tailings = popmany ( \@a, \@b, \@c, \@d );


    You are sticking the backwhacks in front of those arrays, not Perl.
    (If you are using prototypes, then perl will in effect add the backwhacks
    for you, but that is a different matter).

    Since you took the reference, not Perl, then you have to do the
    dereference.



    >
    > sub popmany {
    > my $aref;
    > my @retlist = ();
    > foreach $aref ( @_ ) {
    > push @retlist, pop @$aref;
    > }
    > return @retlist;
    > }
    >
    > Wouldn't it be more accurate to say that perl passes the reference by
    > value? I just find this sort of odd because in both Java (withc uses
    > pass the reference by value) and C++ (which supports pass by
    > reference), I never recall having to dereference a reference like what
    > I have to in perl.


    Perl does "pass the thingamabob by alias". That that thingamabob which was
    passed by alias is a reference is due to your particulars and Perl's
    generals.

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
    , Aug 13, 2007
    #10
  11. grocery_stocker

    Guest

    grocery_stocker <> wrote:
    > If perl can pass stuff by reference, then why do you have to deference
    > it. Like for example
    >
    > @tailings = popmany ( \@a, \@b, \@c, \@d );


    You are sticking the backwhacks in front of those arrays, not Perl.
    (If you are using prototypes, then perl will in effect add the backwhacks
    for you, but that is a different matter).

    Since you took the reference, not Perl, then you have to do the
    dereference.

    >
    > sub popmany {
    > my $aref;
    > my @retlist = ();
    > foreach $aref ( @_ ) {
    > push @retlist, pop @$aref;
    > }
    > return @retlist;
    > }
    >
    > Wouldn't it be more accurate to say that perl passes the reference by
    > value? I just find this sort of odd because in both Java (withc uses
    > pass the reference by value) and C++ (which supports pass by
    > reference), I never recall having to dereference a reference like what
    > I have to in perl.


    Perl does "pass the thingamabob by alias". That that thingamabob which was
    passed by alias is a reference is due to your particulars and not Perl's
    generals.

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
    , Aug 13, 2007
    #11
  12. On Aug 13, 10:08 am, wrote:
    > grocery_stocker <> wrote:
    > > If perl can pass stuff by reference, then why do you have to deference
    > > it. Like for example

    >
    > > @tailings = popmany ( \@a, \@b, \@c, \@d );

    >
    > You are sticking the backwhacks in front of those arrays, not Perl.
    > (If you are using prototypes, then perl will in effect add the backwhacks
    > for you, but that is a different matter).
    >


    Let me get this straight. If I use prototypes, perl will in effect add
    backwhacks?! I'm starting to get these really horrible images of some
    of the AOL engineers using prototypes in Perl scripts and me wondering
    why they were sometimes anal retentive about this. Would you or
    someone else care to give me an example of this?



    Chad
    grocery_stocker, Aug 14, 2007
    #12
  13. grocery_stocker

    Paul Lalli Guest

    On Aug 13, 9:17 pm, grocery_stocker <> wrote:
    > Let me get this straight. If I use prototypes, perl will in effect
    > add backwhacks?!


    Yes. Don't use prototypes. Ever.

    > Would you or someone else care to give me an example of this?


    $ perl -MData::Dumper -e'
    sub foo(\@\@) {
    print Dumper(@_);
    }

    my @one = (1, 2, 3);
    my @two = (4, 5, 6);
    foo(@one, @two);
    '
    $VAR1 = [
    1,
    2,
    3
    ];
    $VAR2 = [
    4,
    5,
    6
    ];

    Compare and contrast with not using a prototype, in which all of @one
    and @two are "flattened" into one big list:

    $ perl -MData::Dumper -e'
    sub foo {
    print Dumper(@_);
    }

    my @one = (1, 2, 3);
    my @two = (4, 5, 6);
    foo(@one, @two);
    '
    $VAR1 = 1;
    $VAR2 = 2;
    $VAR3 = 3;
    $VAR4 = 4;
    $VAR5 = 5;
    $VAR6 = 6;


    Paul Lalli
    Paul Lalli, Aug 14, 2007
    #13
  14. grocery_stocker <> wrote:
    > On Aug 13, 10:08 am, wrote:
    >> grocery_stocker <> wrote:
    >> > If perl can pass stuff by reference, then why do you have to deference
    >> > it. Like for example

    >>
    >> > @tailings = popmany ( \@a, \@b, \@c, \@d );

    >>
    >> You are sticking the backwhacks in front of those arrays, not Perl.
    >> (If you are using prototypes, then perl will in effect add the backwhacks
    >> for you, but that is a different matter).
    >>

    >
    > Let me get this straight. If I use prototypes, perl will in effect add
    > backwhacks?!


    > Would you or
    > someone else care to give me an example of this?



    In addition to all of the ones in the "Prototypes" section in perlsub?

    OK.


    -----------------------------
    #!/usr/bin/perl
    use warnings;
    use strict;

    sub mypush (\@@) {
    my($aref, @list) = @_;
    foreach ( @list ) {
    $aref->[ @$aref ] = $_;
    }
    }

    my @array = qw/zero one two/;
    print "before: @array\n";

    mypush @array, 'three', 'four'; # look Ma! No backslash!
    print "after: @array\n"; # see if @array got modified
    -----------------------------


    --
    Tad McClellan
    email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"
    Tad McClellan, Aug 14, 2007
    #14
  15. grocery_stocker

    Guest

    grocery_stocker <> wrote:
    > On Aug 13, 10:08 am, wrote:
    > > grocery_stocker <> wrote:
    > > > If perl can pass stuff by reference, then why do you have to
    > > > deference it. Like for example

    > >
    > > > @tailings = popmany ( \@a, \@b, \@c, \@d );

    > >
    > > You are sticking the backwhacks in front of those arrays, not Perl.
    > > (If you are using prototypes, then perl will in effect add the
    > > backwhacks for you, but that is a different matter).
    > >

    >
    > Let me get this straight. If I use prototypes, perl will in effect add
    > backwhacks?!


    If the contents of the prototype dictate it, yes.


    > I'm starting to get these really horrible images of some
    > of the AOL engineers using prototypes in Perl scripts and me wondering
    > why they were sometimes anal retentive about this. Would you or
    > someone else care to give me an example of this?


    $ perl -le 'my @x=1..10; foo(@x); sub foo(\@) {print "@_"}; foo(@x)'
    main::foo() called too early to check prototype at -e line 1.
    1 2 3 4 5 6 7 8 9 10
    ARRAY(0x6227e0)

    foo(@x) looks like it should send @x as a list, which is what it does
    initially (but with the warning), but because of the prototype in effect
    the second time the foo-call is compiled, that time it instead sends the
    arrayref.

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
    , Aug 14, 2007
    #15
  16. On 2007-08-13 12:07, Jens Thoms Toerring <> wrote:
    > Josef Moellers <> wrote:
    >> Jens Thoms Toerring wrote:
    >> > grocery_stocker <> wrote:
    >> >>If perl can pass stuff by reference, then why do you have to
    >> >>deference it.
    >> >
    >> > No, you can't. Perl only allows to pass scalars to functions and
    >> > those are passed by value.

    >
    >> Why, then, does the following script print "Bar"?

    >
    >> sub f($) {
    >> $_[0] = 'Bar';
    >> }
    >> my $v = 'Foo';
    >> f($v);
    >> print "$v\n";

    >

    [...]
    > It tells me that I obviously I was writing BS, at least when I
    > didn't mention that using prototypes changes the picture.


    No, prototypes have nothing to do with it. If you omit the "($)", the
    program behaves exactly the same. Perl always passes parameters by
    reference, that is, the elements of @_ are *aliases* of the arguments,
    not *copies*. Thus, when you modify a member of @_, you modify the
    arguments in the caller.

    The usual construct

    sub foo {
    my ($bar, $baz) = @_;
    ...
    }

    simulates passing by value by explicitely making a copy of the
    parameters. Now you can modify $bar and $baz to your heart's content
    without worrying about changing the arguments in the caller.

    hp

    --
    _ | Peter J. Holzer | I know I'd be respectful of a pirate
    |_|_) | Sysadmin WSR | with an emu on his shoulder.
    | | | |
    __/ | http://www.hjp.at/ | -- Sam in "Freefall"
    Peter J. Holzer, Aug 20, 2007
    #16
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jerry
    Replies:
    20
    Views:
    7,930
    Roedy Green
    Sep 9, 2005
  2. blufox
    Replies:
    2
    Views:
    552
  3. Mr A
    Replies:
    111
    Views:
    2,108
  4. Robert
    Replies:
    10
    Views:
    1,367
    E. Robert Tisdale
    Aug 24, 2005
  5. LuB
    Replies:
    6
    Views:
    452
    Mike Wahler
    Sep 23, 2005
Loading...

Share This Page