How can I write "print $F[4] if exists $F[4]" even simpler?

J

jidanni

How can I write
print $F[4] if exists $F[4];
even simpler?
print if exists for $F[4];
print if exists $_ for $F[4];
don't work.
 
U

Uri Guttman

j> How can I write
j> print $F[4] if exists $F[4];
j> even simpler?
j> print if exists for $F[4];
j> print if exists $_ for $F[4];
j> don't work.

well, exists is for checking if a key exists in a hash. you don't have
any hashes there so of course it won't work.

uri
 
F

Frank Seitz

Uri said:
j> How can I write
j> print $F[4] if exists $F[4];
j> even simpler?
j> print if exists for $F[4];
j> print if exists $_ for $F[4];
j> don't work.

well, exists is for checking if a key exists in a hash. you don't have
any hashes there so of course it won't work.

No, exists() checks array elements, too. See perdoc -f exists.

Frank
--
Dipl.-Inform. Frank Seitz
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel

Blog: http://www.fseitz.de/blog
XING-Profil: http://www.xing.com/profile/Frank_Seitz2
 
U

Uri Guttman

j> How can I write
j> print $F[4] if exists $F[4];
j> even simpler?
j> print if exists for $F[4];
j> print if exists $_ for $F[4];
j> don't work.
FS> No, exists() checks array elements, too. See perdoc -f exists.

even so, it is a useless concept IMO. array elements can be never
allocated or filled with undef and there is little reason to know the
difference. this is unlike knowing if a key exists regardless of its
value being set with undef or never being set. exists was changed to
support arrays because of pseudohashes which now are obsolete and
removed from perl. maybe they should remove the array side of exists
too.

uri
 
E

Eric Pozharski

with said:
*SKIP*
FS> No, exists() checks array elements, too. See perdoc -f exists.

And that entry is somewhat strange (underdeveloped?).

*SKIP*
exists was changed to support arrays because of pseudohashes which now
are obsolete and removed from perl. maybe they should remove the array
side of exists too.

I doubt that would ever happen ('breaking old code' spell). Although:

% perl -wle '
$x[25] = "";
print "a$x[4]a" if exists $x[4];
print "b$x[4]b" if defined $x[4];
print "c$x[4]c" if $x[4];
print "d$x[4]d"
__END__
'
Use of uninitialized value $x[4] in concatenation (.) or string at -e line 6.
dd

Me smells XY-problem.
 
F

Frank Seitz

Uri said:
j> How can I write
j> print $F[4] if exists $F[4];
j> even simpler?
j> print if exists for $F[4];
j> print if exists $_ for $F[4];
j> don't work.
FS> No, exists() checks array elements, too. See perdoc -f exists.

even so, it is a useless concept IMO.

This is a completely different point.
array elements can be never
allocated or filled with undef and there is little reason to know the
difference. this is unlike knowing if a key exists regardless of its
value being set with undef or never being set. exists was changed to
support arrays because of pseudohashes which now are obsolete and
removed from perl. maybe they should remove the array side of exists
too.

Here is a simple use case:

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';
}
__END__
0 empty
1 filled
2 empty
3 empty
4 filled

Frank
--
Dipl.-Inform. Frank Seitz
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel

Blog: http://www.fseitz.de/blog
XING-Profil: http://www.xing.com/profile/Frank_Seitz2
 
R

RedGrittyBrick

How can I write
print $F[4] if exists $F[4];
even simpler?
print if exists for $F[4];
print if exists $_ for $F[4];
don't work.

print $F[4];

As in
perl -e '$F[2]=2; $F[4]=4; for $i (1..5) {print $F[$i];}'
24
 
F

Frank Seitz

Ben said:
Quoth Frank Seitz said:
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.

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?

Frank
--
Dipl.-Inform. Frank Seitz
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel

Blog: http://www.fseitz.de/blog
XING-Profil: http://www.xing.com/profile/Frank_Seitz2
 
S

sln

Ben said:
Quoth Frank Seitz said:
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
 
J

Jim Gibson

Frank Seitz said:
Ben said:
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.
 
U

Uri Guttman

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
 
S

sln

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,444
Messages
2,571,709
Members
48,796
Latest member
Greg L.
Top