Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Altering values by reference

Reply
Thread Tools

Altering values by reference

 
 
Gunnar Hjalmarsson
Guest
Posts: n/a
 
      06-26-2003
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

 
Reply With Quote
 
 
 
 
Malte Ubl
Guest
Posts: n/a
 
      06-26-2003
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


 
Reply With Quote
 
 
 
 
Dela Lovecraft
Guest
Posts: n/a
 
      06-26-2003
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



 
Reply With Quote
 
Brian McCauley
Guest
Posts: n/a
 
      06-26-2003
Dela Lovecraft <(E-Mail Removed)> 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\\
 
Reply With Quote
 
Tad McClellan
Guest
Posts: n/a
 
      06-26-2003
Dela Lovecraft <(E-Mail Removed)> 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
http://www.velocityreviews.com/forums/(E-Mail Removed) Perl programming
Fort Worth, Texas
 
Reply With Quote
 
Thens
Guest
Posts: n/a
 
      06-26-2003
On Thu, 26 Jun 2003 12:42:19 +0200
Malte Ubl <(E-Mail Removed)> 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
 
Reply With Quote
 
Dela Lovecraft
Guest
Posts: n/a
 
      06-26-2003
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

 
Reply With Quote
 
Tad McClellan
Guest
Posts: n/a
 
      06-26-2003
Thens <(E-Mail Removed)> 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
(E-Mail Removed) Perl programming
Fort Worth, Texas
 
Reply With Quote
 
Bart Lateur
Guest
Posts: n/a
 
      06-26-2003
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.
 
Reply With Quote
 
Brian McCauley
Guest
Posts: n/a
 
      06-27-2003
Thens <(E-Mail Removed)> 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\\
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Who is altering Subject lines to begin with Antw: Merv Cisco 10 02-17-2006 03:03 AM
altering Request.Headers =?Utf-8?B?QWRhbQ==?= ASP .Net 1 05-20-2005 02:50 AM
Altering a Bi-Directional Data Line Daragoth VHDL 4 06-30-2004 09:12 AM
Altering page content prior to rendering page on browser Rob Heckart ASP .Net 6 11-26-2003 12:36 PM
Altering error for HTMLInputFile when limit exceeded Eric Sabine ASP .Net 0 08-25-2003 03:11 PM



Advertisments