Re: perlsub question..
by shmem (Chancellor) on Jun 23, 2007 at 07:47 UTC
|
does it mean that the following should print 1 (but it doesn't)? perl -le 'x(@y);sub x{$_[0]=1;print @y}'
No, rather
perl -le 'x($y[1]);sub x{$_[0]=1;print $c++,": $_" for @y}'
0:
1: 1
In your version calling x(@y) flattens the (empty) array @y into an empty list. There's no element of @y to be aliased and passed within @_ into x().
Note that indexing an array does not create slots within:
perl -le '$c = $y[10]; x($y[1]);sub x{$_[0]=1;print $c++,": $_" for @y
+}'
0:
1: 1
The array @y isn't 11 elements long merely because I looked at index 10. The sentence you asked about describes that for subroutines. An argument to a subroutine can be a nonexistent element of an array or hash (not an array or hash), and it only springs into existence if told so via its alias inside the sub (by assigning or referencing).
--shmem
_($_=" "x(1<<5)."?\n".q·/)Oo. G°\ /
/\_¯/(q /
---------------------------- \__(m.====·.(_("always off the crowd"))."·
");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
| [reply] [d/l] [select] |
|
|
thank you. that makes sense. few lines down in perlsub, i also read this paragraph:
If no return is found and if the last statement is an expression, its
+value is returned. If the last statement is a loop control structure
+like a foreach or a while, the returned value is unspecified. The emp
+ty sub returns the empty list.
the last two sentences look wrong to me. tried this:
D:\>perl -MData::Dumper -e "sub x{1 for 1..5};@y=x();print 'ha' if def
+ined @y"
ha
so the return value is certainly defined.
The empty sub returns the empty list. that depends on what it's return context is though, not necessarily a empty list.. | [reply] [d/l] [select] |
|
|
$ perl -wle 'sub x{};@y=x(); print "array" if @y'
(nothing)
$ perl -wle 'sub x{};%y=x();print "hash" if %y'
(nothing)
$ perl -wle 'sub x{1..3};@y=x(); print "array" if @y'
array
$ perl -wle 'sub x{a => 1};%y=x();print "hash" if %y'
hash
Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!
| [reply] [d/l] [select] |
|
|
The docs did not say the returned value is undefined, they say it's unspecified! It means that you should not expect the value to make any sense, it could be anything. You could get the 1 you got, you could get an undef, you could get an 'gotcha dude!' string, you could get anything. The result is not specified.
| [reply] |
|
|
perl -e "sub x{ 1 for 1..5 };@y=x(); print Dumper(\@y) if defined @y"
$VAR1 = [
''
];
Looks pretty much "unspecified". Finding out what that sub actually returned is left as an exercise to the reader :-)
that depends on what it's return context is though, not necessarily a empty list..
Yes. Return values are evaluated in the caller's context at subroutine return, which may happen implicitly at the subroutine end.
No, subs always return a list. Sometimes it's empty, sometimes it has only one value. It's up to the caller how it treats that list, and it's up to the sub which elements it returns if it evaluates the context in which it is executed..
This discussion makes me marvel again upon how well written the perl documentation is...
--shmem
_($_=" "x(1<<5)."?\n".q·/)Oo. G°\ /
/\_¯/(q /
---------------------------- \__(m.====·.(_("always off the crowd"))."·
");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
| [reply] [d/l] |
Re: perlsub question..
by GrandFather (Saint) on Jun 23, 2007 at 04:17 UTC
|
use strict;
use warnings;
my @array = (0, 1, 2);
untouched ($array[3]);
print exists $array[3] ? "Element exists" : "No element";
touch ($array[3]);
print "\n", exists $array[3] ? "Element exists" : "No element";
sub untouched {
}
sub touch {
$_[0] = 1;
}
Prints:
No element
Element exists
because the element at index 3 didn't exist until it was referenced in touch.
Update to answer actual question
DWIM is Perl's answer to Gödel
| [reply] [d/l] [select] |
Re: perlsub question..
by guinex (Sexton) on Jun 23, 2007 at 04:10 UTC
|
use Data::Dumper;
sub foo {
$_[0] = undef;
}
sub bar {};
my @a;
@a = ();
foo( $a[0] );
print Dumper \@a;
@a = ();
bar( $a[0] );
print Dumper \@a;
This prints:
$VAR1 = [
undef
];
$VAR1 = [];
As I read the paragraph you quoted, some earlier versions of perl would have produced identical output in both cases.
-guinex
| [reply] [d/l] [select] |
Re: perlsub question..
by NetWallah (Canon) on Jun 23, 2007 at 15:00 UTC
|
The behaviour I see, on "perl, v5.8.8 built for MSWin32-x86-multi-thread" is not consistent with the documentation the OP posted.
> perl -e "my @y;$y[3]=undef; show(@y); x(@y);show(@y);sub show{my $co
+unt=0;print $count++, qq[ : $_;\n] for @_;print qq[----\n\n]}; sub x
+{ @_[3,4,5,6,8]=(3,4,5,6,939);show(@_)}"
--output--
0 : ;
1 : ;
2 : ;
3 : ;
----
0 : ;
1 : ;
2 : ;
3 : 3;
4 : 4;
5 : 5;
6 : 6;
7 : ;
8 : 939;
----
0 : ;
1 : ;
2 : ;
3 : 3;
----
I would document the observed behaviour as :
Array elements are NOT created. Existing elements (which were EXPLICITLY created) will retain modifification in the sub.
"An undefined problem has an infinite number of solutions." - Robert A. Humphrey
"If you're not part of the solution, you're part of the precipitate." - Henry J. Tillman
| [reply] [d/l] |
|
|
sub foo {
print "@_\n";
push @_, 99;
}
@a = (1,2,4);
foo(@a, 666)
Now what's Perl supposed to do with this? Keep in mind that the foo() did not get two parameters, it got FOUR. The three elements of @a and the 666. The first three modifiable, the last readonly. No array was passed.
The docs talk about things like foo( $a[99]) and foo( $h{new_key}), where in an old version the @a would be expanded and the 'new_key' key added into the %h upon calling the subroutine, while in the new versions this is only done if necessary.
This is consistent with things like if (defined($a[99]){... versus $a[99] = 0;.
| [reply] [d/l] [select] |
|
|
Got it (++).
So, would this statement be right :
Elements of @_ are aliased to EXISTING (I was going to say DEFINED, but elements with the value 'undef' are updatable) elements of the passed parameter.
This would explain why the indexes 5,6 and 8 never get created in the code I posted.
"An undefined problem has an infinite number of solutions." - Robert A. Humphrey
"If you're not part of the solution, you're part of the precipitate." - Henry J. Tillman
| [reply] |
|
|
|
|
|
Re: perlsub question..
by ikegami (Patriarch) on Jun 24, 2007 at 17:49 UTC
|
You can't pass an array to a function.
If @a has 0 elements, func(@a) is the same as func().
If @a has 1 element, func(@a) is the same as func($a[0]).
If @a has 2 elements, func(@a) is the same as func($a[0], $a[1]).
If @a has 3 elements, func(@a) is the same as func($a[0], $a[1], $a[2]).
etc.
That's why the text speaks of an "array or hash element".
sub test1 { $a = $_[0]; }
sub test2 { $_[0] = $a; }
my @a;
test1($a[0]); print(scalar(@a), "\n"); # 0
test2($a[0]); print(scalar(@a), "\n"); # 1
Update: Ah shoot! It had written $_[x] where I had meant to write $a[x]. Fixed. Thanks ysth and graff.
| [reply] [d/l] [select] |
|
|
... is the same as ...
But it's not. It's more like
func(map exists($a[$_]) ? $a[$_] : undef, 0..$#a)
(only that map breaks the binding of undefined but existing elements in some way that func(@a) doesn't). | [reply] [d/l] |
Re: perlsub question.. ("alias"?!)
by tye (Sage) on Jun 24, 2007 at 16:40 UTC
|
I object to this wording. You can't have an alias to something that doesn't exist. What is really happening is that, in older Perl, passing a member of an aggregate (an array element or a hash value) forced it to be created so that it could be aliased and the alias put into @_ (because sub call arguments are an lvalue context just like other lvalue context that might not actually change the variable you place in them). In this new Perl, instead a "magic" scalar is created and modifying this magic scalar will cause a new scalar to be inserted into the aggregate (if not already inserted by some other operation) and then cause the modified value to be copied over that member. At no point is this magic placeholder scalar an alias to the potential aggregate member (I bet).
I don't have a bleeding-edge Perl so I can't test, but I can already think of quite a few ways in which this change likely significantly modifies existing behavior (not to mention the ways in which it certainly modifies long-standing behavior). Nothing like throwing in some complex "magic" to break backward compatability and make really explaining lvalue context a lot more complicated for the sake of preventing a minor newbie surprise. And why, again, is it that we can't make <>'s use of @ARGV not be completely stupid? I guess doing so doesn't require enough complicated magic in order to make it appealing to p5p.
At least once in this documentation the term "alias" should be replaced with "magic 'alias'".
| [reply] [d/l] [select] |