Front page | perl.perl5.porters |
Postings from September 2016
[perl #129177] No autovivification, for loop aliasing,
Thread Previous
|
Thread Next
From:
James E Keenan via RT
Date:
September 4, 2016 00:26
Subject:
[perl #129177] No autovivification, for loop aliasing,
Message ID:
rt-4.0.24-26348-1472948760-9.129177-15-0@perl.org
On Sat Sep 03 15:00:21 2016, leszek@dubiel.pl wrote:
>
> Hello!
>
> Here's stripped down version.
> What should I do next? Thank you.
>
>
Yes, for the purpose of discussing autovivification in general (as distinct from the 'autovivification' pragma on CPAN), this is a better code sample.
The documentation of autovivification in the core distribution is clearly less than satisfactory. By consulting four different doc files (as well as the CPAN autovivification documentation), have pieced together the following explanation which should be treated as a *provisional, layperson's* explanation of the phenomenon. The documentation is somewhat adequate in explaining why array and hash elements autovivify when they do, but -- as you have probably found out already -- quite inadequate in explaining why autovivification does *not* happen where you might expect it to.
So here goes.
Perl autovivifies intermediate elements in data structures when it senses that you need to use the lowest elements in such structures as *storage locations*. In Perl, a storage location is referred to as an *lvalue* (where the 'l' refers to the customary 'left-hand side' or an assignment). The context in which you are assigning a value to a storage location -- or when Perl senses that you are about to assign a value to a storage location -- is referred to as *lvalue context*. When you need to assign a value to an array or hash element that doesn't already exist, Perl will create that elements -- and any elements needed to reach that element -- for you. More formally, when you are in lvalue context, perl will autovivify data structures as needed.
>
> #!/usr/bin/perl
>
> use strict;
> use warnings;
>
> my $n = {};
>
> # this is ok...
> for (@{$$n{'x'}}) {
> print 1;
> }
>
In the above you are (IMO) in lvalue context. You are saying, "For each element of the array which is the value of a hash element whose key is 'x' -- and where said hash is dereferenced from $n -- I am going to do something which may (or may not) include storing an element in that array. I need that array to exist even if it does not yet have any elements."
Let me slightly rewrite what we've got so far in a more contemporary notation:
#####
use Data::Dumper;$Data::Dumper::Indent=0;
my $n = {};
for (@{$n->{'x'}}) {
print 1;
}
print Dumper ($n), "\n";
#####
Output:
#####
$VAR1 = {'x' => []};
#####
> # the same throws exception:
> # Can't use an undefined value as an ARRAY reference
> @{$$n{'y'}} and print 2;
>
Here, I would argue, you are *not* in lvalue context. You're not indicating any current or future need to store values in the array which is the value of a hash keyed on 'y'. In fact, if we were to set aside the runtime exception and simply look at the code, we'd probably say, "We're in scalar context; we're asking whether we have a Perl-true (non-zero) number of elements in that array and, if so, we are printing a numeral." Since we're not in lvalue context, there's no call for autovivification of the array, which (I think) renders the array reference undefined.
Here, too, we can update the syntax without changing the problem:
#####
@{$n->{'y'}} and print 2;
#####
That triggers the exception you have encountered. But this exception is to be expected.
> What should I do next?
We don't really know the real-world context if which you encountering this problem. However, if at this point, what you want to do is to create an array -- initially empty but intended for later storage of values -- and you want that array to be the value of a hash keyed on 'y' in a hash referenced from $n, then you could say:
#####
$n->{'y'} = [];
print Dumper ($n), "\n";
#####
Together with the 'x' code above, this would now output:
#####
$VAR1 = {'x' => [],'y' => []};
#####
HTH
References in core distribution:
cpan/perlfaq/lib/perlfaq4.pod
cpan/perlfaq/lib/perlglossary.pod (definitions for 'autovivification' and 'lvalue')
pod/perlref.pod
pod/perlreftut.pod
P5P: We need to work a discussion like the above into our documentation of autovivification. Patches welcome!
Thank you very much.
--
James E Keenan (jkeenan@cpan.org)
---
via perlbug: queue: perl5 status: rejected
https://rt.perl.org/Ticket/Display.html?id=129177
Thread Previous
|
Thread Next