dark314 has asked for the wisdom of the Perl Monks concerning the following question:

When I run this as:
dark314@somebox:~/Perl$ ./tac.pl test zyxwvutsrqpon
I only get 13 characters... the test file is simply a file with letters a - z, it should print all characters backwards
I'm sure there is something wrong here!
#!/usr/bin/perl use strict; #perl excercise, reverse cat... my @file; while (<>) { chomp; push @file, $_; } foreach (@file) { my $test = pop (@file); print $test; } print "\n";
------------------------------------UPDATE-------------------------------------


Thanks. I am aware of reverse() lol. The idea was to use push() and pop(). I guess I understand now my problem, using a foreach there evaluates the size of @file each time I think, and by the time it gets halfway thru it believes that it has gone thru the entire set? ?? how confusing. I will use while from now on

Replies are listed 'Best First'.
Re: Using Push and Pop.
by ikegami (Patriarch) on Aug 23, 2006 at 19:31 UTC
    foreach (@file) { my $test = pop (@file); print $test; }

    should be

    while (@file) { my $test = pop (@file); print $test; }

    In reply to your updated question,

    while (@file) works because it evaluates the size of @file before each iteration.

    foreach (@file) processes element 0 on the first pass, element 1 on the second pass, etc. On the 14th pass, it should process element 13. However, the loop ends because @file only has elements 0 through 12 left.

Re: Using Push and Pop.
by Joost (Canon) on Aug 23, 2006 at 19:33 UTC
Re: Using Push and Pop. - response to update
by imp (Priest) on Aug 23, 2006 at 22:07 UTC
    This will demonstrate why popping items off of the list you are iterating over is a bad idea:
    use strict; use warnings; my @list = 'a'..'z'; for my $letter (@list) { my $popped = pop @list; printf "letter: %s popped: %s list: %s\n",$letter,$popped,join('', +@list); }
    Output:
    letter: a popped: z list: abcdefghijklmnopqrstuvwxy letter: b popped: y list: abcdefghijklmnopqrstuvwx letter: c popped: x list: abcdefghijklmnopqrstuvw letter: d popped: w list: abcdefghijklmnopqrstuv letter: e popped: v list: abcdefghijklmnopqrstu letter: f popped: u list: abcdefghijklmnopqrst letter: g popped: t list: abcdefghijklmnopqrs letter: h popped: s list: abcdefghijklmnopqr letter: i popped: r list: abcdefghijklmnopq letter: j popped: q list: abcdefghijklmnop letter: k popped: p list: abcdefghijklmno letter: l popped: o list: abcdefghijklmn letter: m popped: n list: abcdefghijklm
    By the time you reach letter 'm' you have removed enough items from the end of the list that you are now at the new end.

    Update - added quote from perlsyn

     If any part of LIST is an array, "foreach" will get very
     confused if you add or remove elements within the loop
     body, for example with "splice".   So don't do that
    
      Based on that perlsyn quote, another (inefficient) solution would be to convert the array into a list:
      foreach (map $_, @file) { my $test = pop (@file); print $test; }
Re: Using Push and Pop.
by imp (Priest) on Aug 23, 2006 at 19:32 UTC
    Why are you popping entries off the end of the @file list inside a loop where you are iterating over the entries in @file?

    for my $f (reverse @file) { print $f; }
    Or
    while (@file) { print pop @file; }
Re: Using Push and Pop.
by chromatic (Archbishop) on Aug 24, 2006 at 05:20 UTC

    A: It's confusing and difficult to read otherwise.

    Q: Why do updates go after the original text?