Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Autovivification by foreach

Reply
Thread Tools

Autovivification by foreach

 
 
Frank Seitz
Guest
Posts: n/a
 
      03-12-2009
Hi,

given the following code:

use strict;
use warnings;

my (@a,$ref);
push @a,@$ref;

Perl throws an exception:
Can't use an undefined value as an ARRAY reference
Seems plausible.

We are modifying the code:

my (@a,$ref);
push @a,$_ for @$ref;

Now, there is no exception anymore. Perl creates the array on the fly.
Why is it so? What is the difference?

Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel
 
Reply With Quote
 
 
 
 
Uri Guttman
Guest
Posts: n/a
 
      03-12-2009
>>>>> "FS" == Frank Seitz <(E-Mail Removed)> writes:

FS> my (@a,$ref);
FS> push @a,@$ref;

FS> Perl throws an exception:
FS> Can't use an undefined value as an ARRAY reference
FS> Seems plausible.

FS> We are modifying the code:

FS> my (@a,$ref);
FS> push @a,$_ for @$ref;

FS> Now, there is no exception anymore. Perl creates the array on the fly.
FS> Why is it so? What is the difference?

in the first case @$ref is readonly as it is input to push and can't be
modified. autovivification only happens on lvalues when they are undef
and used where a ref should be.

on the other hand for (modifier or main loop style) makes $_ an alias
into each element of its list. and $_ is read/write so the elements
should be lvalues. so perl will autovivify the array ref since you might
be modifying elements. it can't tell (the executed code could be a sub
call, etc.) so it has to do this before the loop starts. this little
test shows what happens:

perl -le 'push @a,$_ for @$ref; print $ref'
ARRAY(0x816324

for much more on autoviv read my tutorial:

http://sysarch.com/Perl/autoviv.txt

uri

--
Uri Guttman ------ http://www.velocityreviews.com/forums/(E-Mail Removed) -------- http://www.sysarch.com --
----- Perl Code Review , Architecture, Development, Training, Support ------
--------- Free Perl Training --- http://perlhunter.com/college.html ---------
--------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
 
Reply With Quote
 
 
 
 
Frank Seitz
Guest
Posts: n/a
 
      03-13-2009
Uri Guttman wrote:
>>>>>> "FS" == Frank Seitz <(E-Mail Removed)> writes:

>
> FS> my (@a,$ref);
> FS> push @a,@$ref;
>
> FS> Perl throws an exception:
> FS> Can't use an undefined value as an ARRAY reference
> FS> Seems plausible.
>
> FS> We are modifying the code:
>
> FS> my (@a,$ref);
> FS> push @a,$_ for @$ref;
>
> FS> Now, there is no exception anymore. Perl creates the array on the fly.
> FS> Why is it so? What is the difference?
>
> in the first case @$ref is readonly as it is input to push and can't be
> modified. autovivification only happens on lvalues when they are undef
> and used where a ref should be.


Thanks, the readonly/lvalue distinction in this context was not clear to me.

> on the other hand for (modifier or main loop style) makes $_ an alias
> into each element of its list. and $_ is read/write so the elements
> should be lvalues. so perl will autovivify the array ref since you might
> be modifying elements. it can't tell (the executed code could be a sub
> call, etc.) so it has to do this before the loop starts.


This explanation is not plausible to me. Perl autovivifies before
loop start, because the loop might be modifying array elements?
How is this possible? The autovivificated array is empty.
It is clear that the body of the loop is never executed.

In my opinion it would make more sense when Perl would
throw an exception in this case too.

Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel
 
Reply With Quote
 
A. Sinan Unur
Guest
Posts: n/a
 
      03-13-2009
Frank Seitz <(E-Mail Removed)> wrote in
news:(E-Mail Removed):

> Uri Guttman wrote:
>>>>>>> "FS" == Frank Seitz <(E-Mail Removed)> writes:

>>
>> FS> my (@a,$ref);
>> FS> push @a,@$ref;
>>
>> FS> Perl throws an exception:
>> FS> Can't use an undefined value as an ARRAY reference
>> FS> Seems plausible.
>>
>> FS> We are modifying the code:
>>
>> FS> my (@a,$ref);
>> FS> push @a,$_ for @$ref;
>>
>> FS> Now, there is no exception anymore. Perl creates the array on
>> the fly. FS> Why is it so? What is the difference?
>>
>> in the first case @$ref is readonly as it is input to push and can't
>> be modified. autovivification only happens on lvalues when they are
>> undef and used where a ref should be.

>


....

> This explanation is not plausible to me. Perl autovivifies before
> loop start, because the loop might be modifying array elements?
> How is this possible? The autovivificated array is empty.
> It is clear that the body of the loop is never executed.
>
> In my opinion it would make more sense when Perl would
> throw an exception in this case too.


First, note that I do think this behavior is a little quirky.

However, it seems to me that autovivification in this context is useful.

It allows you to avoid writing code to check $ref before, say, adding
elements to some array for further processing. In that context, one may
not care about the definedness of $ref per se but only about if it
points to further elements to process.

Uri's explanation made sense to me. Hash element autovivification has
its quirks too but it is useful under similar circumstances.

If you don't want autovivification and you want to avoid the exception,
you can write:

push @a, @$ref if ref $ref eq 'ARRAY';

Or, if you want the exception, write:

die '$ref is not defined' unless defined $ref;
die '$ref is not an array ref' unless ref $ref eq 'ARRAY';

Sinan

--
A. Sinan Unur <(E-Mail Removed)>
(remove .invalid and reverse each component for email address)

comp.lang.perl.misc guidelines on the WWW:
http://www.rehabitation.com/clpmisc/
 
Reply With Quote
 
Uri Guttman
Guest
Posts: n/a
 
      03-13-2009
>>>>> "FS" == Frank Seitz <(E-Mail Removed)> writes:

>> into each element of its list. and $_ is read/write so the elements
>> should be lvalues. so perl will autovivify the array ref since you might
>> be modifying elements. it can't tell (the executed code could be a sub
>> call, etc.) so it has to do this before the loop starts.


FS> This explanation is not plausible to me. Perl autovivifies before
FS> loop start, because the loop might be modifying array elements?
FS> How is this possible? The autovivificated array is empty.
FS> It is clear that the body of the loop is never executed.

if perl didn't autovivify the lvalue in the for loop, then it would die
if you attempted to modify an array ref element. perl assumes that since
the array ref being used (and it is undef) is an lvalue then you
may/will write to it so it autovivifies for you.

FS> In my opinion it would make more sense when Perl would
FS> throw an exception in this case too.

it doesn't because of DWIM. autovivification is a subtle thing at times
and very useful most of the time. it does have some edges like deep
access using exists will autovivify. perl6 fixed that problem. maybe it
could not autovivify the array ref unless an element is modified but i
can live with that as it is.

uri

--
Uri Guttman ------ (E-Mail Removed) -------- http://www.sysarch.com --
----- Perl Code Review , Architecture, Development, Training, Support ------
--------- Free Perl Training --- http://perlhunter.com/college.html ---------
--------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
 
Reply With Quote
 
Peter J. Holzer
Guest
Posts: n/a
 
      03-14-2009
On 2009-03-13 15:54, Uri Guttman <(E-Mail Removed)> wrote:
>>>>>> "FS" == Frank Seitz <(E-Mail Removed)> writes:
> >> into each element of its list. and $_ is read/write so the elements
> >> should be lvalues. so perl will autovivify the array ref since you might
> >> be modifying elements. it can't tell (the executed code could be a sub
> >> call, etc.) so it has to do this before the loop starts.

>
> FS> This explanation is not plausible to me. Perl autovivifies before
> FS> loop start, because the loop might be modifying array elements?
> FS> How is this possible? The autovivificated array is empty.
> FS> It is clear that the body of the loop is never executed.
>
> if perl didn't autovivify the lvalue in the for loop, then it would die
> if you attempted to modify an array ref element.


You can't attempt to do that since the loop body is never executed.

hp
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
A difficulty with *surprising autovivification* in using %HASH sm Perl Misc 1 01-04-2007 07:02 PM
Autovivification within deep nested hash niall.macpherson@ntlworld.com Perl Misc 7 05-15-2006 01:44 PM
Rite, Block locals and Autovivification John Carter Ruby 1 12-01-2003 10:02 PM
Re: foreach loop error Luc Kumps ASP .Net 0 08-22-2003 10:16 PM
Re: foreach loop error Kevin Spencer ASP .Net 0 08-22-2003 09:11 PM



Advertisments