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 Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Strange behaviour for shift() 1

Status
Not open for further replies.

AlanD2

Technical User
Aug 23, 2006
3
GB
I need to be able to maintain a stack which varies in length according to circumstances. I want to use shift() and unshift() at the left, and push() and pop() at the right.

I have noticed strange behaviour when using shift(). My simple example below shows the problem.

In this example, when I use shift() "manually", the stack is correctly shifted five times. But when I use "for" or "foreach", the stack is only shifted three times. When I check the remaining contents of the stack, "four" and "five" are still present.

I would be grateful if anyone could explain this.

Forum users probably know many other ways to accomplish the same objective, but I would prefer to learn why shift() does not work the correct number of times (5).

Regards,
Alan

#------------------------------
#!/usr/bin/perl -w

my @stack = qw(one two three four five) ;

print ( shift ( @stack). "\n" ) ;
print ( shift ( @stack). "\n" ) ;
print ( shift ( @stack). "\n" ) ;
print ( shift ( @stack). "\n" ) ;
print ( shift ( @stack). "\n" ) ;

print "-----------------\n";

@stack = qw(one two three four five) ;

foreach ( @stack )
{
print ( shift ( @stack). "\n" ) ;
}
print "-----------------\n";

@stack = qw(one two three four five) ;

my $numStackEntries = @stack ;
my $i ;

for ( $i = 0 , $i < $numStackEntries, $i++ )
{
print ( shift ( @stack). "\n" ) ;
}
 
Code:
@stack = qw(one two three four five) ;

foreach ( @stack )
{                    
    print ( shift ( @stack). "\n" ) ;
}

On the first iteration, the `foreach' loop is on the first element of the array (one). Inside the loop, that's removed from the beginning of the array and printed.

On the second iteration, the `foreach' loop moves to the second element of the array. Since the original first one was removed from the array, the second element is now "three". Inside the loop, "two" is removed from the array and printed.

On the third iteration, the `foreach' loop moves to the third element of the array. Since "one" and "two" have been removed, the array is now "three", "four", "five". Inside the loop, "three" is removed and printed.

On the fourth iteration, the `foreach' loop looks for the fourth element of the array. Since the array now only contains "four" and "five", there is no fourth element, so the loop exits. There are often problems changing the number of elements in an array inside a foreach loop that uses that array.

If you want to achieve the same thing:
Code:
while(@stack) {
    print ( shift ( @stack). "\n" ) ;
}

i.e. while there are still elements in @stack, remove one and print it.
 
Oh, for your third example, your `for' loop is incorrectly constructed. If you use semicolons instead of commas, it'll work as you expect. A more Perl-ish way of doing the same thing would be:
Code:
for ( 1 .. $numStackEntries ) {
    print ( shift ( @stack). "\n" );
}

What's happening at the moment there is that you're giving `for' a three-element list ($i=0, $i<$numStackEntries,$i++), so it loops three times (`for' and `foreach' are identical, so in this case it's like a foreach loop over three elements).
 
Thanks. That worked perfectly.

That was probably the clearest technical explanation I've seen.

Regards,
Alan
 
Thanks for the second explanation.

If I hadn't wasted so much of your time, I would say this whole example is hilarious :)

I managed to construct the exact set of circumstances to ensure that the "for" and "foreach" loop gave identical answers:

a) I chose five variables for @stack

b) I constructed the "for" loop incorrectly such that it still produced an answer. Any other faulty construction would probably have failed.

I suppose I have to be good at something :)

Regards,
Alan
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top