Re: How come @_ gets changed here?
by tobyink (Canon) on Jun 10, 2017 at 10:36 UTC
|
No, @_ is an alias to the sub's arguments. That's how things like chomp work:
sub my_chomp {
$_[0] =~ s/\r?\n\z//sm;
}
my $var = "foo\n";
my_chomp $var;
print "[[$foo]]\n";
perlsub says:
The array @_ is a local array, but its elements are aliases for the actual scalar parameters.
| [reply] [d/l] [select] |
Re: How come @_ gets changed here?
by LanX (Saint) on Jun 10, 2017 at 11:10 UTC
|
That is doubly confusing code ...
2 effects are overlaying.
- the @arr inside the sub is the same like outside, because you didn't use my again. (Change the name and strict will throw an error, otherwise the function is a closure)
- the elements of @_ are aliases of the elements passed, i.e. the values of @arr
(like demonstrated by Tobyink)
Since you reassign these elements with the map, you are effectively changing @_, it's like writing @_ = map { 2 * $_ } @_;
Change this to my @arr = map { 2 * $_ } @_; and your problem disappears
Style tips how to avoid this
- it's always a good strategy to choose meaningful names for variables instead of arr or array , like this strict would have caught the error.
- don't declare variables on top of your program if you only intend to use them much later.
| [reply] [d/l] [select] |
Re: How come @_ gets changed here?
by kcott (Archbishop) on Jun 10, 2017 at 18:55 UTC
|
&function(...)
it raises a red flag.
Unless you can expand that to
# In the following code, I am aware of the leading ampersand.
# I have read, and fully understood, all the implications of
# writing the code, as is; having read and completed digested
# all information in http://perldoc.perl.org/perlsub.html.
# I totally intended that code to be written as is because
# ...
# ...
# ...
&function(...)
To understand my code better, refer to
"perlsub - Perl subroutines".
Unless you can confidently fill in all of the blanks in the above comments,
you've almost certainly done something wrong.
| [reply] [d/l] [select] |
|
|
Not sure what you mean here. Are you complaining about the use of the ampersand with the function call? I usually advise against that too, but in this case the behavior is the same with or without it.
| [reply] |
|
|
You raise a valid point and I'm definitely not "complaining" about anything.
Like you, I "usually advise against" that usage.
My intention was to point out, quite unequivocally, that there was a difference between
&sub(@args)
and
sub(@args)
Reviewing what I originally wrote, it's perhaps not immediately obvious that,
without a valid reason for writing
&sub(@args)
it would generally be preferable to write
sub(@args)
Thankyou for raising this point and providing an opportunity for clarification.
| [reply] [d/l] [select] |
|
|
| [reply] |
|
|
|
|
Re: How come @_ gets changed here?
by ikegami (Patriarch) on Jun 11, 2017 at 02:21 UTC
|
Perl arguments are passed by reference. Change them in the sub, and they'll change in the caller and vice-versa.
| [reply] |
|
|
| [reply] [d/l] [select] |
|
|
"Pass By Reference" (vs. "Pass By Value") is a general computer science term which is implemented as "aliasing" in Perl.
Perl's "references" are totally different.
update
Context matters: Canadians are North Americans proud not to be Americans. ;)
update
OK, I consider this perlsub#Pass-by-Reference a documentation bug.
| [reply] |
Re: How come @_ gets changed here?
by Anonymous Monk on Jun 10, 2017 at 14:56 UTC
|
The behavior of this script in perl 5.26 is so weird that it seems like it must be a bug.
Before calling the sub test_this @arr: 1 2 3 4 5 6 7 8 9 10
Inside the sub, before the map @arr: 1 2 3 4 5 6 7 8 9 10
Inside the sub, before the map @_ = 1 2 3 4 5 6 7 8 9 10
Inside the sub, after the map @arr: 2 4 6 8 10 12 14 16 18 20
Use of uninitialized value $_[0] in join or string at foo line 11.
Use of uninitialized value $_[3] in join or string at foo line 11.
Use of uninitialized value $_[6] in join or string at foo line 11.
Use of uninitialized value $_[9] in join or string at foo line 11.
Inside the sub, after the map @_ = _ Use of uninitialized value $_[0]
+ in join or string at foo line 11.
_ Use of uninitialized value $_[3] in join or string at foo line 11.
_ Use of uninitialized value $_[6] in join or string at foo line 11.
After calling the sub test_this @arr: 2 4 6 8 10 12 14 16 18 20
If I throw in print Dumper(@_), I get this:
panic: attempt to copy freed scalar 7fe03e8040b0 to 7fe03e82c858 at /o
+pt/local/lib/perl5/5.26/darwin-thread-multi-2level/Data/Dumper.pm lin
+e 602.
Anyone know what's going on? | [reply] [d/l] [select] |
|
|
my @a=(3);
sub x {
@a = map {$_*2} @_;
"@_" eq "6" or die
}
&x(@a);
says that the first bad commit is a5f4850559, which makes v5.24.0, or more specifically v5.23.2, the first version with this behavior. Since that commit is heavy on the internals and I'm not an expert on that, I can't say more at the moment, although it does seem like a regression to me.
| [reply] [d/l] |
|
|
my @a=(3,4);
sub x {
@a = ();
print "[$_]" for @_;
print "\n";
}
x(@a);
you get:
$ perl5220 -w ~/tmp/p
Use of uninitialized value $_ in concatenation (.) or string at /home/
+davem/tmp/p line 9.
Use of uninitialized value $_ in concatenation (.) or string at /home/
+davem/tmp/p line 9.
[][]
Dave. | [reply] [d/l] [select] |
|
|
|
|
|
|
|
|
|
|
|
| [reply] |
Re: How come @_ gets changed here?
by pritesh_ugrankar (Monk) on Jun 10, 2017 at 22:35 UTC
|
Respected Monks,
Thank you for taking time to reply.
I used & at the beginning of a function because, as per Learning Perl book, I am to use an & before calling the function, else, I might accidentally end up calling a perl built-in. In fact there is a link given in the book https://www.learning-perl.com/2013/05/why-we-teach-the-subroutine-ampersand/ which if I understood right, is stating it's better to use & when one is not sure.
But from the posts here, I reckon it's not encouraged. So I'm not sure if I should or shouldn't use the &.
I will later try to test on other version(s) of Perl and see how it goes.
| [reply] [d/l] |
|
|
In that article, brian d foy is saying that using & sometimes avoids trouble for people who are very new to Perl. What the rest of us are saying is that using & causes more trouble for intermediate-level Perl programmers. Decide for yourself which category you are in, but remember that & is old-perl.
Mr foy suggests that it is ok to type "&foo;", but never do that, because it actually passes @_ to foo. Always put the parens. "foo();" or "&foo();", but not "&foo;" unless you really mean it.
| [reply] |
| A reply falls below the community's threshold of quality. You may see it by logging in. |