Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Array Range Problem 2

Status
Not open for further replies.

awingnut

Programmer
Feb 24, 2003
759
US
I have a foreach loop that operates on the elements of an array. However, the size of the array is variable. Here is the code segment:
Code:
if ($#name>1) {
   .
   .
   .
                foreach my $part ($name[2..$#name]) {
   .
   .
   .
Occasionally $#name will evaluate to 2. That seems to be when I get the error:

Use of uninitialized value in range (or flip)

Is it illegal to have a range with the same start and end values? Is there a way around this so I don't have to duplicate the code when $#name=2? TIA.
 
As far as i know, 2..2 is OK. But if array length is less than 2, then it should give you the error.
WHat is your array like?


--------------------------------------------------------------------------
I never set a goal because u never know whats going to happen tommorow.
 
I may have made an error in observation. It appears now that the value of $#name doesn't matter. It just doesn't like me to use it in the range.
 
you should use @name[2..$#name] which is an array slice, instead of $name[2..$#name] which is a single scalar which has no range. An example shows the problem:

Code:
my @array = (2..10);
print $array[3..5];
print "\n";
print @array[3..5];

the above prints:

2
345

it appears $array[3..5] is being interpreted as $array[0]


 
or a more approriate example would be:

my @array = (2..10);
print $array[2..$#array];
print "\n";
print @array[2..$#array];

which prints:

2
45678910

$array[2..$#array] is still being interpreted as $array[0] I guess because the range is invalid in scalar context so perl just defaults to the 0th position of the array.
 
Ah, thanks. It gets a little confusing, to this beginner, understand when $ and @ are to be used with array references.
 
The range operator certainly is valid in scalar context, and indeed is very useful indeed. However, in that context it has nothing to do with ranges :) It acts as a flip-flop (see perlop).

In scalar context, it begins by checking the left operand for truth. Since the left operand is a constant expression in this case (2), it compares it to the current value of the $. variable (see perlvar to see what that's for if you don't already). If $. is not equal to 2, it returns a false value (the empty string), which when used as an array index is the same as 0. In fact, since you haven't yet read from a file, $. is undefined, which is why you're getting the uninitialised warning.

If $. happened to be equal to 2 (i.e. you'd read exactly two lines from the most recently accessed filehandle), the `..' operator would return true (1) and so you'd get the first element in the array.

Look at these three examples (pass some file to the script on the command line so that there's some lines for it to read).

First one - uninitialised warning - array element not numeric warning - prints "zero"
Code:
#!/usr/bin/perl -w
use strict;

my $bal = 'fda';

my @array = qw/zero one two three four/;
print $array[2..$bal],"\n";
We've now read one line from <>, so $. is 1. No uninitialised warning anymore, since it has a value. Still prints "zero", since it's not equal to 2
Code:
#!/usr/bin/perl -w
use strict;

my $stuff = <>;

my $bal = 'fda';

my @array = qw/zero one two three four/;
print $array[2..$bal],"\n";

Now we've read two lines so $. equals "2". The ".." operator now returns 1, so this prints "one".
Code:
#!/usr/bin/perl -w
use strict;

my $stuff = <>;
$stuff = <>;

my $bal = 'fda';

my @array = qw/zero one two three four/;
print $array[2..$bal],"\n";

Hopefully someone has an idea of what I'm talking about!

BTW good spot on the scalar context Kevin, I hadn't noticed that at all.
 
Ishnid,

I understand what you are saying. Very valuable insight. Have a star.
 
The range operator certainly is valid in scalar context,

I agree with your examples Ishnid, but it seems convoluted and I can't see why a person would use something like that in actual code. That can't be considered a good coding practice I would think.
 
It was more an attempt to explain what was happening than an attempt to show a use for the `..' operator in scalar context.

A better example of something that could actually be useful
Code:
#!/usr/bin/perl -w
use strict;

while(<DATA>) {
   print if ( 5 .. 10 ); # print lines 5 to 10

   # start printing at a line starting with `t'
   # stop after printing first line starting with `f'
   print if ( /^t/ .. /^f/ );
}
__DATA__
one
two
three
four
five
six
seven
eight
nine
ten
eleven
 
this looks like list context to me:

print if ( 5 .. 10 )

as does this:

print if ( /^t/ .. /^f/ );



 
I'm afraid you're wrong there Kevin. There's a tendency to automatically think "list context" whenever you see the ".." operator. The full explanation is in perlop, though personally I found it tricky to understand fully without playing with some examples.

The expression to be evaluated in an `if' statement is always in scalar context. If it was in list context, the following two lines would be the same:
Code:
print if ( 5 .. 10 );
print if ( 5, 6, 7, 8, 9, 10 );

As you can see if you run the code, the results of using these two lines are not the same.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top