Altering values by reference

Discussion in 'Perl Misc' started by Gunnar Hjalmarsson, Jun 26, 2003.

  1. Dela Lovecraft wrote:
    > Is there a way of altering a variable sent as a reference to a
    > subroutine in Perl *without* using a return value?


    <snip>

    > Suppose I had a sub doSomething which added 10 to a value. Assuming
    > I sent it by reference, it could like something like this:
    >
    > sub doSomething
    > {
    > my $reference = shift;
    > my $value = $$reference;
    > return ($value + 10);
    > }
    >
    > And it would be called:
    > my $x = 1;
    > my $y = doSomething(\$x);
    >
    > No problem. But is there a way I could call the sub such that the
    > value of $x could be altered in situ without returning a value,
    > even over different packages? Something like:
    >
    > my $x = 1;
    > myOtherPackage::doSomething(\$x); #such that $x now equals 11


    sub doSomething { ${$_[0]} += 10 }

    / Gunnar

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
    Gunnar Hjalmarsson, Jun 26, 2003
    #1
    1. Advertising

  2. Gunnar Hjalmarsson

    Malte Ubl Guest

    Dela Lovecraft wrote:
    > Dear All,
    >
    > I was having a discussion with a die-hard Pascal programmer yesterday, and a
    > point was raised I couldn't answer, and I said I would try and find the
    > answer for him. Is there a way of altering a variable sent as a reference
    > to a subroutine in Perl *without* using a return value? As I recall, in
    > Pascal, you send to a function using either the value or declaring it as
    > var, in which case in can get altered in the procedure:
    >
    > procedure myProc(x : Integer; var y : Integer)
    >
    > Whatever is sent to the procedure as x remains unchanged, but anything which
    > happens to y (because of the var keyword) is changed in the original
    > variable. I think (sorry of the syntax for Pascal is off, but it has been a
    > long time.) Is such a thing possible in Perl?


    Parameters in Perl are always passed by reference (That is, the
    references reside inside the magical array @_). "Pass by value" only
    happens when you take things out of @_ (e.g. by calling shift without
    arguments). If you access @_ directly you get the desired behavior.

    some code: (untested)

    sub inc {
    $_[0]++
    }

    my $i = 0;

    inc($i);

    print $i

    shows that $i has been modified inside the subroutine inc.

    bye
    malte
    Malte Ubl, Jun 26, 2003
    #2
    1. Advertising

  3. Dear All,

    I was having a discussion with a die-hard Pascal programmer yesterday, and a
    point was raised I couldn't answer, and I said I would try and find the
    answer for him. Is there a way of altering a variable sent as a reference
    to a subroutine in Perl *without* using a return value? As I recall, in
    Pascal, you send to a function using either the value or declaring it as
    var, in which case in can get altered in the procedure:

    procedure myProc(x : Integer; var y : Integer)

    Whatever is sent to the procedure as x remains unchanged, but anything which
    happens to y (because of the var keyword) is changed in the original
    variable. I think (sorry of the syntax for Pascal is off, but it has been a
    long time.) Is such a thing possible in Perl?

    Suppose I had a sub doSomething which added 10 to a value. Assuming I sent
    it by reference, it could like something like this:

    sub doSomething
    {
    my $reference = shift;
    my $value = $$reference;
    return ($value + 10);
    }

    And it would be called:
    my $x = 1;
    my $y = doSomething(\$x);

    No problem. But is there a way I could call the sub such that the value of
    $x could be altered in situ without returning a value, even over different
    packages? Something like:

    my $x = 1;
    myOtherPackage::doSomething(\$x); #such that $x now equals 11


    Any help would be really appreciated.


    Dela
    Dela Lovecraft, Jun 26, 2003
    #3
  4. Dela Lovecraft <> writes:

    > sub doSomething
    > {
    > my $reference = shift;
    > my $value = $$reference;
    > return ($value + 10);
    > }
    >
    > And it would be called:
    > my $x = 1;
    > my $y = doSomething(\$x);
    >
    > No problem. But is there a way I could call the sub such that the value of
    > $x could be altered in situ without returning a value, even over different
    > packages?


    packages are irrelevant unless you are using _symbolic_ references.

    Something like:

    > my $x = 1;
    > myOtherPackage::doSomething(\$x); #such that $x now equals 11


    No problem

    package myOtherPackage;
    sub doSomething
    {
    my $reference = shift;
    $$reference += 10;
    }

    I you dont like putting the \ in the call to doSomething() you can put
    it in a prototype instead. Or you can manipulate $_[0] directly rather
    than using shift.

    --
    \\ ( )
    . _\\__[oo
    .__/ \\ /\@
    . l___\\
    # ll l\\
    ###LL LL\\
    Brian McCauley, Jun 26, 2003
    #4
  5. Dela Lovecraft <> wrote:

    > Is there a way of altering a variable sent as a reference
    > to a subroutine in Perl *without* using a return value?



    Yes.

    In fact, you can alter a variable even if it is NOT a reference.

    (as long as it IS an "lvalue".)


    [snip: call-by-value vs. call-by-reference]


    > Is such a thing possible in Perl?



    Yes.


    > Suppose I had a sub



    Then you would surely read the docs for subroutines (perlsub.pod)
    and come across this:

    Because the assignment copies the values, this also has the effect
    of turning call-by-reference into call-by-value. Otherwise a
    function is free to do in-place modifications of C<@_> and change
    its caller's values.

    and you would have already known the answer to your question. :)



    To get call-by-reference (the default) in Perl:

    by_ref($x);
    sub by_ref { $_[0] += 10 }

    To get (the effect of) call-by-value in Perl:

    by_val($x);
    sub by_val { my $num = $_[0]; $num += 10 } # make copy, operate on copy


    Neither of them use what is termed a "reference" in Perl (ie. perlref.pod).


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
    Tad McClellan, Jun 26, 2003
    #5
  6. Gunnar Hjalmarsson

    Thens Guest

    On Thu, 26 Jun 2003 12:42:19 +0200
    Malte Ubl <> wrote:

    >Dela Lovecraft wrote:



    >Parameters in Perl are always passed by reference (That is, the
    >references reside inside the magical array @_). "Pass by value" only
    >happens when you take things out of @_ (e.g. by calling shift without
    >arguments). If you access @_ directly you get the desired behavior.


    Now i have another question are both these same

    sub doSomething{
    my ($arg1, $arg2) = @_;
    ..
    }

    sub doSomething{
    my $arg1 = shift;
    my $arg2 = shift;
    ..
    }


    Since you (and perldoc perlsub) say that the @_ contains aliases to scalar parameters and when you shift it they become values. Iam slightly confused. Im my first assignment am I assigning the references then ? I have code like these that has been working properly.

    Thanks in advance

    Regards,
    Thens
    Thens, Jun 26, 2003
    #6
  7. To al that answered.

    Thanks very much. I knew it was possible somehow, but I couldn't quite get
    my head round it. I don't do a vast amount of coding, so was a bit lost.

    Thanks again,


    Dela
    Dela Lovecraft, Jun 26, 2003
    #7
  8. Thens <> wrote:

    > are both these same
    >
    > sub doSomething{
    > my ($arg1, $arg2) = @_;
    > ..
    > }
    >
    > sub doSomething{
    > my $arg1 = shift;
    > my $arg2 = shift;
    > ..
    > }



    Yes, with regard to call-by-value vs. call-by-reference.

    No, with respect to their effects on the contents of @_.


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
    Tad McClellan, Jun 26, 2003
    #8
  9. Gunnar Hjalmarsson

    Bart Lateur Guest

    Dela Lovecraft wrote:

    >Is there a way of altering a variable sent as a reference
    >to a subroutine in Perl *without* using a return value?


    Yes. The values in @_° are aliases to the original values. So modify
    $_[0] directly, and you'll modify the first parameter; etc.

    For example:

    sub inc {
    $_[0]++;
    }

    my $x = 3;
    inc $x;
    print $x; # prints "4"

    It's only when assigning the contents out of @_ to your local (usually
    lexical) variables, that you actually make a copy.

    sub foo {
    my $x = shift; # copy
    my($y, $z) = @_; # copy
    $x++; $y++; $z++;
    # The original parameters are still unaltered
    }

    --
    Bart.
    Bart Lateur, Jun 27, 2003
    #9
  10. Thens <> writes:

    > sub doSomething{
    > my ($arg1, $arg2) = @_;
    > ..
    > }
    >
    > sub doSomething{
    > my $arg1 = shift;
    > my $arg2 = shift;
    > ..
    > }


    > Since you (and perldoc perlsub) say that the @_ contains aliases
    > to scalar parameters and when you shift it they become values.


    No, they remain aliases (lvalues) even when you shift. It is when you
    evaluate then in an rvalue context (i.e. a context like that found on
    RHS of an assignment) they become (r)values.

    sub one {
    # Due to a mis-feature of the Perl compiler this genreates spurious
    # compile-time error:
    # Can't modify shift in postincrement (++)
    # If I try to do:
    # shift()++;
    # Actually you can, but you have to fool the compiler in to not noticing.
    $_++ for shift;
    }

    sub two {
    $_[0]++;
    }

    my $q = 1;
    one($q);
    print "After one(): $q\n";
    two($q);
    print "After two(): $q\n";
    __END__
    After one(): 2
    After two(): 3

    --
    \\ ( )
    . _\\__[oo
    .__/ \\ /\@
    . l___\\
    # ll l\\
    ###LL LL\\
    Brian McCauley, Jun 27, 2003
    #10
  11. Gunnar Hjalmarsson

    Malte Ubl Guest

    Brian McCauley wrote:
    > $_++ for shift;


    hehe :)
    Malte Ubl, Jun 27, 2003
    #11
    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. Daragoth
    Replies:
    4
    Views:
    600
    Just an Illusion
    Jun 30, 2004
  2. Eric Sabine
    Replies:
    0
    Views:
    329
    Eric Sabine
    Aug 25, 2003
  3. Rob Heckart
    Replies:
    6
    Views:
    531
    Rob Heckart
    Nov 26, 2003
  4. =?Utf-8?B?QWRhbQ==?=

    altering Request.Headers

    =?Utf-8?B?QWRhbQ==?=, May 19, 2005, in forum: ASP .Net
    Replies:
    1
    Views:
    415
    Steven Cheng[MSFT]
    May 20, 2005
  5. Ben Fidge
    Replies:
    3
    Views:
    612
    Mr Newbie
    Nov 6, 2005
Loading...

Share This Page