From: sln on
On Fri, 05 Mar 2010 12:59:29 +0100, Frank Seitz <devnull4711(a)web.de> wrote:

>Ben Morrow wrote:
>> Quoth Frank Seitz <devnull4711(a)web.de>:
>>>
>>> my @a;
>>> $a[1] = 4711;
>>> $a[4] = 4712;
>>>
>>> for (my $i = 0; $i < @a; $i++) {
>>> printf "%d %s\n",$i,exists $a[$i]? 'filled': 'empty';
>>
>> WRONG. You mean 'defined'. Whether an element responds to 'exists' or
>> not depends on whether memory has been allocated to hold that element
>> yet, which is not generally something you can predict.
>
>In my understanding an array element "exists", when I assigned a
>value to it, otherwise not.
>
Yes, exists() is more the an elements memory state: initialized or not.
Defined'nes is the state of the elements value. And it can be possible
that it is not defined, whether it exists or not.

For arrays, existence is a test to determine if it has ever been touched
as opposed to defined'nes when acting on its value.

People think exists is just a test for hash keys, but it is very usefull
when randomly indexing an array and perhaps it needs to get the air
taken out of it, or something else distinguishing between initialized
and defined.

-sln
From: Jim Gibson on
In article <7vca11Fj56U1(a)mid.individual.net>, Frank Seitz
<devnull4711(a)web.de> wrote:

> Ben Morrow wrote:
> > Quoth Frank Seitz <devnull4711(a)web.de>:
> >>

> > WRONG. You mean 'defined'. Whether an element responds to 'exists' or
> > not depends on whether memory has been allocated to hold that element
> > yet, which is not generally something you can predict.
>
> In my understanding an array element "exists", when I assigned a
> value to it, otherwise not.
>
> my @a;
> $a[1] = 4711;
> $a[3] = undef;
> $a[4] = 4712;
>
> print "exists:\n";
> for (my $i = 0; $i < @a; $i++) {
> printf " %d %s\n",$i,exists $a[$i]? 'filled': 'empty';
> }
> print "defined:\n";
> for (my $i = 0; $i < @a; $i++) {
> printf " %d %s\n",$i,defined $a[$i]? 'filled': 'empty';
> }
> __END__
> exists:
> 0 empty
> 1 filled
> 2 empty
> 3 filled
> 4 filled
> defined:
> 0 empty
> 1 filled
> 2 empty
> 3 empty
> 4 filled
>
> I get what I expect. Where is the problem?

One problem would be that your expectations might differ from those of
others, including mine. In your scenario, I would expect that, since
the normal meaning of "array" is a contiguous set of members, that
$a[0] and $a[2] would 'exist', since an array of length 5 needs to be
allocated to hold $a[4], and $a[5] would not 'exist'. However, the
exists function does not yield what I would expect:

#!/usr/local/bin/perl

use strict;
use warnings;

my @a;
$a[1] = 1;
$a[3] = undef;
$a[4] = 4;

for( my $i = 0; $i <= 5 ; $i++ ) {
printf " %d %s\n", $i,
( $a[$i] ? 'filled' :
( defined $a[$i] ? 'defined' :
( exists $a[$i] ? 'exists':
'non-existent' )));
}

_OUTPUT_

0 non-existent
1 filled
2 non-existent
3 exists
4 filled
5 non-existent

I would have expected 'exists' for elements 0 and 2 and 'non-existent'
only for 5.

--
Jim Gibson
From: Uri Guttman on
>>>>> "JG" == Jim Gibson <jimsgibson(a)gmail.com> writes:

JG> my @a;
JG> $a[1] = 1;
JG> $a[3] = undef;
JG> $a[4] = 4;

JG> for( my $i = 0; $i <= 5 ; $i++ ) {
JG> printf " %d %s\n", $i,
JG> ( $a[$i] ? 'filled' :

0 would fail that and be defined but not filled. i would print all three
possible states for each entry to really get the picture.

JG> ( defined $a[$i] ? 'defined' :
JG> ( exists $a[$i] ? 'exists':
JG> 'non-existent' )));
JG> }

JG> _OUTPUT_

JG> 0 non-existent
JG> 1 filled
JG> 2 non-existent
JG> 3 exists
JG> 4 filled
JG> 5 non-existent

JG> I would have expected 'exists' for elements 0 and 2 and 'non-existent'
JG> only for 5.

remember, exists tests arrays for where any allocation occured. this
makes sense in some way. preallocating an array only allocates the
slots, not the SV's that go into them. even assigning undef to a slot
allocated storage for the SV. so defined will pass on an empty slot OR a
slot assigned undef. only exists will tell if the slot was ever assigned
to.


my @a;
$a[1] = 0;
$a[3] = undef;
$a[4] = 4;

foreach my $i ( 0 .. $#a ) {
print "$i: ", exists $a[$i] ? 'exists ' : '',
defined $a[$i] ? 'defined ' : '',
$a[$i] ? 'true' : '',
"\n" ;
}


0:
1: exists defined
2:
3: exists
4: exists defined true

note that [3] exists but isn't defined. it was allocated with an SV
holding undef. [0] and [2] were never allocated so they don't even
exist.

now for the news that keys will work on arrays in 5.12. will it just
create a list of the full indices? or only those indices that exist?
also will each() now work on arrays? that will solve the age old (mostly
newbie) request to get the index AND value from iterating over a
list. p6 solves this with the .kv method/accessor which returns an
index/value pair. each() would be similar to this in returning the next
index/value pair as it does for hashes. something like this would be
cool:

while( my( $i, $val ) = each( @array ) ) {

of course you better not modify the array length during this.
maybe changing values would be allowed ($val should be an alias if
possible to the element).

uri

--
Uri Guttman ------ uri(a)stemsystems.com -------- http://www.sysarch.com --
----- Perl Code Review , Architecture, Development, Training, Support ------
--------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
From: sln on
On Fri, 05 Mar 2010 09:51:51 -0800, Jim Gibson <jimsgibson(a)gmail.com> wrote:

>One problem would be that your expectations might differ from those of
>others, including mine. In your scenario, I would expect that, since
>the normal meaning of "array" is a contiguous set of members, that
>$a[0] and $a[2] would 'exist', since an array of length 5 needs to be
>allocated to hold $a[4], and $a[5] would not 'exist'. However, the
>exists function does not yield what I would expect:
>
>#!/usr/local/bin/perl
>
>use strict;
>use warnings;
>
>my @a;
>$a[1] = 1;
>$a[3] = undef;
>$a[4] = 4;
>
>for( my $i = 0; $i <= 5 ; $i++ ) {
> printf " %d %s\n", $i,
> ( $a[$i] ? 'filled' :
> ( defined $a[$i] ? 'defined' :
> ( exists $a[$i] ? 'exists':
> 'non-existent' )));
>}
>
>_OUTPUT_
>
> 0 non-existent
> 1 filled
> 2 non-existent
> 3 exists
> 4 filled
> 5 non-existent
>
>I would have expected 'exists' for elements 0 and 2 and 'non-existent'
>only for 5.

When you "initialize" an element, either hash or array, it goes into
existence, not before.
Even though you can do
@array;
$array[100] = undef;
elements 0-99 are not initialized. However, the size of the array
springs up to 101 elements, of which only element 101 is initialized.

Hash's aren't based on continuous numeric indexes so the phrase
"exists" is more appropriate to hash's than arrays.

For arrays, the need to know if elements have been initialized, does have
its place separate from defined, and therefore should be thought of as
value initialization.

Hash and array elements don't exist until they are initialized.

I believe the below statement to be true (but can't say for sure):
The actual @array is just a header that maintains slot information
(pointers) for elements as they are "initialized", when the actual
memory allocation for the data occurs.

So, think exists for hashes, initialized for arrays.

-sln