Pass by reference question
Pass by reference question
am 13.08.2007 04:26:54 von grocery_stocker
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.
Re: Pass by reference question
am 13.08.2007 04:34:12 von Sherm Pendley
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?
> I just find this sort of odd because in both Java ... and C++ ...
Perl is Perl. It's neither Java nor C++. Leave your preconceptions at
the door please.
sherm--
--
Web Hosting by West Virginians, for West Virginians: http://wv-www.net
Cocoa programming in Perl: http://camelbones.sourceforge.net
Re: Pass by reference question
am 13.08.2007 04:41:32 von grocery_stocker
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'.
Re: Pass by reference question
am 13.08.2007 11:43:05 von JT
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 ___ jt@toerring.de
\__________________________ http://toerring.de
Re: Pass by reference question
am 13.08.2007 11:52:03 von Josef Moellers
Jens Thoms Toerring wrote:
> grocery_stocker wrote:
>=20
>>If perl can pass stuff by reference, then why do you have to deference
>>it.
>=20
>=20
> 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] =3D 'Bar';
}
my $v =3D 'Foo';
f($v);
print "$v\n";
Josef
--=20
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
Re: Pass by reference question
am 13.08.2007 11:54:21 von Josef Moellers
Jens Thoms Toerring wrote:
> grocery_stocker wrote:
>=20
>>If perl can pass stuff by reference, then why do you have to deference
>>it.
>=20
>=20
> 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] =3D 'Bar';
}
my $v =3D 'Foo';
f($v);
print "$v\n";
And what does this script's error message tell us?
sub f($) {
$_[0] =3D 'Bar';
}
f('Foo');
With all due respect,
Josef
--=20
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
Re: Pass by reference question
am 13.08.2007 13:44:46 von anno4000
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
Re: Pass by reference question
am 13.08.2007 13:50:31 von Josef Moellers
grocery_stocker wrote:
> If perl can pass stuff by reference, then why do you have to deference
> it. Like for example
>=20
> @tailings =3D popmany ( \@a, \@b, \@c, \@d );
>=20
>=20
> sub popmany {
> my $aref;
> my @retlist =3D ();
> foreach $aref ( @_ ) {
> push @retlist, pop @$aref;
> }
> return @retlist;
> }
>=20
>=20
> 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.
>=20
Perl passes variables by reference and dereferences them automagically.=20
If you explicitly pass a reference ('\@a'), you'll have to dereference=20
it explicitly.
I.e. in your example, popmany is passed four references to references to =
arrays.
Josef
--=20
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
Re: Pass by reference question
am 13.08.2007 14:07:16 von JT
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 ___ jt@toerring.de
\__________________________ http://toerring.de
Re: Pass by reference question
am 13.08.2007 15:26:48 von anno4000
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
Re: Pass by reference question
am 13.08.2007 19:08:19 von xhoster
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
Re: Pass by reference question
am 14.08.2007 03:17:45 von grocery_stocker
On Aug 13, 10:08 am, xhos...@gmail.com 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
Re: Pass by reference question
am 14.08.2007 03:49:50 von Paul Lalli
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
Re: Pass by reference question
am 14.08.2007 03:53:44 von Tad McClellan
grocery_stocker wrote:
> On Aug 13, 10:08 am, xhos...@gmail.com 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/"
Re: Pass by reference question
am 14.08.2007 04:33:01 von xhoster
grocery_stocker wrote:
> On Aug 13, 10:08 am, xhos...@gmail.com 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
Re: Pass by reference question
am 20.08.2007 18:07:32 von hjp-usenet2
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.
| | | hjp@hjp.at |
__/ | http://www.hjp.at/ | -- Sam in "Freefall"