Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Very basic question on using references inside functions

Reply
Thread Tools

Very basic question on using references inside functions

 
 
Mark Seger
Guest
Posts: n/a
 
      08-15-2005
I'd have thought this would have been answered in some of the
documentation on using references but if it was I missed it.

I understand that if I want to call a function and pass it a reference
to a scalar I can then modify that scalar within the function as follows:

sub foo {
my $ref=shift;
$$ref='new value';
}

and it works just fine. However, I want to use that scalar within the
function many times and don't want to call it $$ref every time because
it feels clumsy.

Is there some other way? I thought I could make a reference to that
reference by something like $var=\$$ref and just access $var but that
didn't work. My REAL motive for asking is I have some code that passes
parameters by value and I'd like to go back and pass them by reference
without have to change all the other code that touches them.

Then again, maybe the perlish way to do it IS to refer to them
everywhere as $$ref, $@ref or %$ref just to be clearer about what it
really going on.

-mark
 
Reply With Quote
 
 
 
 
Anno Siegel
Guest
Posts: n/a
 
      08-15-2005
Mark Seger <(E-Mail Removed)> wrote in comp.lang.perl.misc:
> I'd have thought this would have been answered in some of the
> documentation on using references but if it was I missed it.
>
> I understand that if I want to call a function and pass it a reference
> to a scalar I can then modify that scalar within the function as follows:
>
> sub foo {
> my $ref=shift;
> $$ref='new value';
> }
>
> and it works just fine. However, I want to use that scalar within the
> function many times and don't want to call it $$ref every time because
> it feels clumsy.


It's how it's done, clumsy or not.

> Is there some other way? I thought I could make a reference to that
> reference by something like $var=\$$ref and just access $var but that
> didn't work.


That would give you an additional layer of reference and make the
access more complicated, not less.

> My REAL motive for asking is I have some code that passes
> parameters by value and I'd like to go back and pass them by reference
> without have to change all the other code that touches them.


Perl *does* pass scalars "by reference" in the sense that a parameter
value can be changed from within the function. Example:

sub foe {
$_[ 0] = 'new value';
}
my $x = 'old value';
fum( $x);
print "$x\n";

If you want to access the variable under a meaningful name (instead of
$_[ 0]) you can use a one-shot for loop to get an alias (this is also
called topicalization):

sub fum {
for my $variable ( $_[ 0] ) {
$variable = 'new value';
}
}

So references are not really necessary to change a scalar variable
from within a sub. (Aggregates are a different matter.) However,
a code change will be necessary either way.

Anno
--
If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers.
 
Reply With Quote
 
 
 
 
Gunnar Hjalmarsson
Guest
Posts: n/a
 
      08-15-2005
Mark Seger wrote:
> I understand that if I want to call a function and pass it a reference
> to a scalar I can then modify that scalar within the function as follows:
>
> sub foo {
> my $ref=shift;
> $$ref='new value';
> }
>
> and it works just fine. However, I want to use that scalar within the
> function many times and don't want to call it $$ref every time because
> it feels clumsy.


<snip>

> My REAL motive for asking is I have some code that passes
> parameters by value and I'd like to go back and pass them by reference
> without have to change all the other code that touches them.


So you don't care whether the passed variable is changed? In that case,
there is of course the obvious dereference way:

sub foo {
my $var = ${ $_[0] };
$var = 'new value';
}

OTOH, then you wouldn't gain much from passing references instead of
values...

--
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl
 
Reply With Quote
 
Mark Seger
Guest
Posts: n/a
 
      08-15-2005

> Perl *does* pass scalars "by reference" in the sense that a parameter
> value can be changed from within the function. Example:
>
> sub foe {
> $_[ 0] = 'new value';
> }
> my $x = 'old value';
> fum( $x);
> print "$x\n";
>

What I meant by 'pass by reference' is that any changes you make in the
function are reflected back at caller who will then see changes to that
parameter. I believe what perl does is 'pass by value', in that it
makes a copy of the data, thereby allowing you to change it without fear
of clobbering the orignal value.

> If you want to access the variable under a meaningful name (instead of
> $_[ 0]) you can use a one-shot for loop to get an alias (this is also
> called topicalization):
>
> sub fum {
> for my $variable ( $_[ 0] ) {
> $variable = 'new value';
> }
>

}
I do this all the time for all variables, even in for loops as I find
references like @_ or $_ read very poorly, but that's me.

-mark
 
Reply With Quote
 
Anno Siegel
Guest
Posts: n/a
 
      08-15-2005
Mark Seger <(E-Mail Removed)> wrote in comp.lang.perl.misc:
>
> > Perl *does* pass scalars "by reference" in the sense that a parameter
> > value can be changed from within the function. Example:
> >
> > sub foe {
> > $_[ 0] = 'new value';
> > }
> > my $x = 'old value';
> > fum( $x);
> > print "$x\n";
> >

> What I meant by 'pass by reference' is that any changes you make in the
> function are reflected back at caller who will then see changes to that
> parameter. I believe what perl does is 'pass by value', in that it
> makes a copy of the data, thereby allowing you to change it without fear
> of clobbering the orignal value.


You believe wrong. The code example above shows that changes to sub
arguments (the elements of @_) are indeed visible to the caller. The
"call-by-value" thing happens when you assign the content of @_ to
local variables, as in "my ( $x, $y, $z) = @_;". If you change $x etc.
in the sub body, nothing is changed in the environment. If you change
$_[ 0] etc. directly, it is.

> > If you want to access the variable under a meaningful name (instead of
> > $_[ 0]) you can use a one-shot for loop to get an alias (this is also
> > called topicalization):
> >
> > sub fum {
> > for my $variable ( $_[ 0] ) {
> > $variable = 'new value';
> > }
> >

> }
> I do this all the time for all variables, even in for loops as I find
> references like @_ or $_ read very poorly, but that's me.


That's an unrelated point. The aliasing behavior of "for" is the same
whether you use an explicit variable or the default $_.

sub fum {
for ( $_[ 0] ) {
$_ = 'new value';
}
}

would have illustrated my point just as well.

Anno
--
If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers.
 
Reply With Quote
 
xhoster@gmail.com
Guest
Posts: n/a
 
      08-15-2005
Mark Seger <(E-Mail Removed)> wrote:
> I'd have thought this would have been answered in some of the
> documentation on using references but if it was I missed it.
>
> I understand that if I want to call a function and pass it a reference
> to a scalar I can then modify that scalar within the function as follows:
>
> sub foo {
> my $ref=shift;
> $$ref='new value';
> }
>
> and it works just fine. However, I want to use that scalar within the
> function many times and don't want to call it $$ref every time because
> it feels clumsy.


Tough it out. It stops feeling clumsy after a while.

> Is there some other way? I thought I could make a reference to that
> reference by something like $var=\$$ref and just access $var but that
> didn't work.


That is effectively the same thing as $var=$ref; It doesn't change the way
you dereference it.


> My REAL motive for asking is I have some code that passes
> parameters by value and I'd like to go back and pass them by reference
> without have to change all the other code that touches them.


If it currently passes parameters (effectively) by value, and it does the
right thing, then wouldn't changing it to pass them by reference cause it
to do the wrong thing unless you change all that other code anyway?

You could use typeglobs (or whatever it is I am supposed to call those
things). I don't particularly recommend it, but I have used it in a pinch.

use strict;

my $x='j' x 10;

print "$x\n";
foo3($x);
print "$x\n";

sub foo3 {
our $y;
*y = \$_[0];
$y =~ s/j/k/g;
};

Xho

--
-------------------- http://NewsReader.Com/ --------------------
Usenet Newsgroup Service $9.95/Month 30GB
 
Reply With Quote
 
Anno Siegel
Guest
Posts: n/a
 
      08-15-2005
<(E-Mail Removed)> wrote in comp.lang.perl.misc:
> Mark Seger <(E-Mail Removed)> wrote:


[variable passing]

> You could use typeglobs (or whatever it is I am supposed to call those
> things). I don't particularly recommend it, but I have used it in a pinch.
>
> use strict;
>
> my $x='j' x 10;
>
> print "$x\n";
> foo3($x);
> print "$x\n";
>
> sub foo3 {
> our $y;
> *y = \$_[0];
> $y =~ s/j/k/g;
> };


Yes, but why?

sub foo4 { $_[ 0] =~ s/j/k/g }

or

sub foo5 { s/j/k/g for shift }

do the same thing directly.

Anno
--
If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers.
 
Reply With Quote
 
xhoster@gmail.com
Guest
Posts: n/a
 
      08-16-2005
http://www.velocityreviews.com/forums/(E-Mail Removed)-berlin.de (Anno Siegel) wrote:
> <(E-Mail Removed)> wrote in comp.lang.perl.misc:
> > Mark Seger <(E-Mail Removed)> wrote:

>
> [variable passing]
>
> > You could use typeglobs (or whatever it is I am supposed to call those
> > things). I don't particularly recommend it, but I have used it in a
> > pinch.
> >
> > use strict;
> >
> > my $x='j' x 10;
> >
> > print "$x\n";
> > foo3($x);
> > print "$x\n";
> >
> > sub foo3 {
> > our $y;
> > *y = \$_[0];
> > $y =~ s/j/k/g;
> > };

>
> Yes, but why?


The point of a short but complete example script (like people here are
always asking for) is to show how something is done. It is not to show why
it is done. The why is covered in the prose. I thought it was pretty
obvious why to do that.
>
> sub foo4 { $_[ 0] =~ s/j/k/g }


unlike $_[0], the name of $y can be arbitrarily chosen. If you are going
to use the variable fifty times in your subroutine, that is quite a
benefit.

Xho

--
-------------------- http://NewsReader.Com/ --------------------
Usenet Newsgroup Service $9.95/Month 30GB
 
Reply With Quote
 
Anno Siegel
Guest
Posts: n/a
 
      08-16-2005
<(E-Mail Removed)> wrote in comp.lang.perl.misc:
> (E-Mail Removed)-berlin.de (Anno Siegel) wrote:
> > <(E-Mail Removed)> wrote in comp.lang.perl.misc:
> > > Mark Seger <(E-Mail Removed)> wrote:

> >
> > [variable passing]
> >
> > > You could use typeglobs (or whatever it is I am supposed to call those
> > > things). I don't particularly recommend it, but I have used it in a
> > > pinch.
> > >
> > > use strict;
> > >
> > > my $x='j' x 10;
> > >
> > > print "$x\n";
> > > foo3($x);
> > > print "$x\n";
> > >
> > > sub foo3 {
> > > our $y;
> > > *y = \$_[0];
> > > $y =~ s/j/k/g;
> > > };

> >
> > Yes, but why?

>
> The point of a short but complete example script (like people here are
> always asking for) is to show how something is done. It is not to show why
> it is done. The why is covered in the prose. I thought it was pretty
> obvious why to do that.


You say "in a pinch", but I don't see the pinch that makes a solution
involving package variables attractive.

> > sub foo4 { $_[ 0] =~ s/j/k/g }

>
> unlike $_[0], the name of $y can be arbitrarily chosen. If you are going
> to use the variable fifty times in your subroutine, that is quite a
> benefit.


You can have that lexically too:

for my $y ( shift ) {
$y =~ s/j/k/g;
}

(Admitted, it doesn't scale well for more than one variable.)

You know the reason to avoid package variables: exposure. If you have
a rogue function do_something() (say, imported from somewhere), which does

sub do_something {
# ....
our $y = 'something else';
}

then calling do_something() while "*y = \ $_[ 0]" is in effect has
unexpected and hard-to-trace consequences:

sub foo6 {
our $y;
*y = \ shift();
do_something()
$y =~ s/g/k/g;
}

now sets its argument to "somethink else".

Anno
--
If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers.
 
Reply With Quote
 
Mark Seger
Guest
Posts: n/a
 
      08-16-2005
Anno Siegel wrote:
> Mark Seger <(E-Mail Removed)> wrote in comp.lang.perl.misc:
>
>>>Perl *does* pass scalars "by reference" in the sense that a parameter
>>>value can be changed from within the function. Example:
>>>
>>> sub foe {
>>> $_[ 0] = 'new value';
>>> }
>>> my $x = 'old value';
>>> fum( $x);
>>> print "$x\n";
>>>

>>
>>What I meant by 'pass by reference' is that any changes you make in the
>>function are reflected back at caller who will then see changes to that
>>parameter. I believe what perl does is 'pass by value', in that it
>>makes a copy of the data, thereby allowing you to change it without fear
>>of clobbering the orignal value.

>
>
> You believe wrong. The code example above shows that changes to sub
> arguments (the elements of @_) are indeed visible to the caller. The
> "call-by-value" thing happens when you assign the content of @_ to
> local variables, as in "my ( $x, $y, $z) = @_;". If you change $x etc.
> in the sub body, nothing is changed in the environment. If you change
> $_[ 0] etc. directly, it is.


yikes! I was indeed wrong. I guess my habit of ALWAYS saying
my $xyz=shift
for each parameter has protected me in my ignorance.

but from yours and other notes I think I'll be a lot more comfortable
with passing references around now.

-mark
 
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
I found some very odd behaviour in Python's very basic types Sunjay Varma Python 4 03-10-2011 05:05 PM
A very **very** basic question mdh C Programming 57 09-26-2008 03:25 PM
very very basic question aghazalp Python 6 04-02-2006 09:35 PM
Very very very basic question Peter C Programming 14 02-14-2005 09:46 AM
very Very VERY dumb Question About The new Set( ) 's Raymond Arthur St. Marie II of III Python 4 07-27-2003 12:09 AM



Advertisments