Re^5: referencing slices - love that DWIM
by Fletch (Bishop) on May 17, 2008 at 13:39 UTC
|
A list is an ephermeral thing; a transient set of values on the call stack. There's no way to take a reference to it since it has no permanent home to which to refer. An array on the other hand has a permanent location in memory to which a pointer can be obtained.
The cake is a lie.
The cake is a lie.
The cake is a lie.
| [reply] |
|
|
A list is an ephermeral thing; a transient set of values on the call stack
Ok ... so if, as the docs say, \(@foo) returns a list, then precisely what does [\(@foo)] return ? Is it (something like) "a reference to an array comprising the list returned by \(@foo)" ? (What's the correct terminology ?)
Cheers, Rob
| [reply] [d/l] [select] |
|
|
use Data::Dumper qw( Dumper );
my @foo = qw( a b c );
my $x = [ \( @foo ) ];
print Dumper( $x ), "\n";
${ $x->[1] } = 'z';
print join( "\n", @foo ), "\n";
print Dumper( $x ), "\n";
The cake is a lie.
The cake is a lie.
The cake is a lie.
| [reply] [d/l] [select] |
|
|
However, from the point of view of a perl programmer they are as near as damnit the same thing.
| [reply] |
|
|
Except for in the edge cases, which is where thinking they are the same thing gets you into trouble:
- the \( @array ) vs \@array behavior in question here
- push|splice|etc require an actual ARRAY as their first argument, not a LIST
- a LIST and an ARRAY will behave differently in scalar context (contrast scalar qw( a b c ) with scalar @{[ qw( a b c ) ]})
Those are three that readily come to my pre-morning-caffeine brane, but there's certainly others. Yes in most cases they'll behave the same, but you need to understand that it is a simplification and know where the idea breaks down. Otherwise you'll be unpleasantly surprised after you have to go chasing down squirrelly context induced wonkyness.
The cake is a lie.
The cake is a lie.
The cake is a lie.
| [reply] [d/l] [select] |
Re^5: referencing slices - love that DWIM
by almut (Canon) on May 17, 2008 at 14:15 UTC
|
... then wouldn't [\(@foo)] have to return a reference to that list ?
Not sure what it would have to... :) but as it is, it returns
a reference to an anonymous array which has been initialised with
references to the list's individual elements/values. Something quite different.
| [reply] [d/l] |
|
|
Not sure what it would have to... :)
Yeah ... sometimes I get a bit literal about these things. My reasoning (undoubtedly flawed) is along the lines that the square brackets ([]) return a reference to whatever is within those brackets ... and if it's a list that's within those brackets (as stated by the docs), then those square brackets must be returning a reference to that list.
it returns a reference to an anonymous array which has been initialised with references to the list's individual elements/values
Something about that doesn't feel right to me. Do you mean "it returns a reference to an anonymous array which has been initialised with the list's individual elements/values" - and that, in this case, those "elements/values" are actually references ?
It's probably a bit confusing to be asking these sorts of questions in terms of the return of \(@foo). Surely there are simpler constructs that also return a list. Does, eg (1..10) return a list ?
Cheers, Rob
| [reply] [d/l] [select] |
|
|
Do you mean "it returns a reference to an anonymous array which has
been initialised with the list's individual elements/values" - and
that, in this case, those "elements/values" are actually references ?
Depends on exactly which list we're talking about... I was
referring to the original values stored in @foo, and you're
presumably thinking of the values after the referencing operation \(...) has
been applied — in a human language it's not as easy to express
things clearly as it is in Perl :)
Anyhow, the net effect of this is:
my @foo = (1, 2, "foo");
my $bar = [\(@foo)];
use Data::Dumper;
print Dumper $bar;
__END__
$VAR1 = [
\1,
\2,
\'foo'
];
IOW, "$bar->[2]" would produce something like SCALAR(0x814ec28),
which you'd need to dereference (${$bar->[2]}) to get at the value
"foo".
And yes, (1..10) is a list.
| [reply] [d/l] [select] |
|
|
Re^5: referencing slices - love that DWIM
by ysth (Canon) on May 18, 2008 at 05:57 UTC
|
To me, it is blatantly obvious that DWIMness dictates that \(@foo) ought to return the same as [@foo]
I've never liked \(@foo) and thought it should be no different from \@foo
(a reference to the array @foo).
My reasoning (undoubtedly flawed) is along the lines that the square brackets ([]) return a reference to whatever is within those brackets ...
Flawed, yes. [] creates a new array, initialized from the list given, and returns
a reference to it. This differs from "return[ing] a reference to whatever is within"
in that it is a shallow copy, so \@foo is affected by later changes to @foo's elements, while
[@foo] is not (unless those elements are references to other things which are changed.)
| [reply] |
|
|
I've never liked \(@foo)
Oh ... that now makes *3* of us that I know of.
I first came across this construct while building PGPLOT-2.18 on perl 5.8. One (or more) of the test files contained a line of code like (from test10.p):
pgline(128, \(0..127), $$img2D[127]);
The author (and I) were amazed to discover that what was intended to be the 2nd arg, was in fact 128 separate arguments. We were both convinced that this was a perl bug .... but were assured in no uncertain terms that it wasn't :-)
Update: As ysth says, it's not a bug and never was. (It has always been documented in perl 5.8.) But these were the early days of 5.8, neither Karl nor myself had studied the changes from 5.6. Why would we ? The behaviour was simply so counter-intuitive to us that it just *had* to be a bug :-)
Cheers, Rob | [reply] [d/l] |
|
|
It's definitely not a bug, but that doesn't make me like it.
| [reply] |