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

I'm using Windows Subsystem for Linux Perl and I'm getting weird results when printing an array

while (scalar @list_words) { test_if_letters_are_included(); foreach(@list_words) { print "$_\n"; } my @array = qw(this that the other thing); say "@array"; say "@list_words"; say scalar @list_words; }

I truncated the output for brevity. Prints:

...ZONDA ZONED ZONES ZOOID ZOOKS ZOOMS ZOONS ZORIS ZOSMA ZUDDA ZULUS ZUNIS this that the other thing ZUNIS 8471

Any guesses as why I would only get the last element of the @list_words array?

Even weirder yet. If I change "say" to "print" on the @array I get an output that is a mix of both arrays!

while (scalar @list_words) { test_if_letters_are_included(); foreach(@list_words) { print "$_\n"; } my @array = qw(this that the other thing); print "@array"; say "@list_words"; say scalar @list_words; }

Again, I truncated the output for brevity. Prints:

...ZONDA ZONED ZONES ZOOID ZOOKS ZOOMS ZOONS ZORIS ZOSMA ZUDDA ZULUS ZUNIS this that the other thing ZUNIShat the other thingABASE 8471

"ABASE" is the index 14 of @list_words.

Replies are listed 'Best First'.
Re: Bizarre Perl behavior?
by Corion (Patriarch) on Jan 30, 2022 at 20:04 UTC

    Most likely, the content of @list_words is not what you think it is. Maybe it contains terminal control codes, or one single large line.

    Note that you output @list_words twice, with no delimiter in between, which will make debugging this much harder.

    My first attempt at debugging this would be to add some non-whitespace characters around the elements of @list_words while printing them, and cut down @list_words to say 10 elements that you can also share here:

    splice @list_words, 10; # inspect only the first 10 elements use Data::Dumper; local $Data::Dumper::Useqq = 1; # output strings with whitespace chara +cters escaped while (scalar @list_words) { test_if_letters_are_included(); foreach(@list_words) { print "list_words:<$_>\n"; print Dumper $_; # also show the string with whitespace escaped } my @array = qw(this that the other thing); print "@array"; #say "@list_words"; say scalar @list_words; }

      Thanks for the quick reply. I'll give it a try.

      I failed to mention that when I run this on my Windows version of Perl it does not have the output problem and prints as expected.

        > when I run this on my Windows version of Perl it does not have the output problem and prints as expected.

        sounds like you are printing control code characters which are messing with the terminal.

        Like a CR without LF might overwrite the same line over and over again.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery

Re: Bizarre Perl behavior?
by LanX (Saint) on Jan 30, 2022 at 20:24 UTC
    the problem is most likely inside test_if_letters_are_included() and since you are looping over while (scalar @list_words) you are expecting the array to be reduced "somewhere", but without showing us where.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

      I though that at first too. But the subroutine has a prompt for user input after the previous standard output. So the loop stops after every standard out until the array is empty. Both of the print statements are printing after the subroutine so it should be printing same @list_words. Right?

      The subroutine asks the user for a string of characters and uses them as a character set in a regex. Any of the words that don't contain any of the characters are removed from the list.

      sub test_if_letters_are_included{ # Ask for input say 'Which letters would you like to use?:'; # Capture user input my $input = <STDIN>; # Remove the trailing newline chomp $input; # Change the input to upper case. $input = uc $input; # create a character set for the regex my $regex ="[$input]"; my @temp_list; for (@list_words) { if ($_ =~ /$regex/g) { push @temp_list, $_; } } @list_words = @temp_list; }

        As a general tip for future questions, it's considered good manners here to include a SSCCE.

        Without a SSCCE it's hard to tell, but your test_if_letters_are_included subroutine appears to be setting a global variable @list_words. Is that right? In your code, where is @list_words declared? What is its scope?

        As a matter of general programming style, a subroutine that sets a global variable is a red flag to me. As for why:

        Another way to write that:

        sub test_if_letters_are_included { # Ask for input say 'Which letters would you like to use?:'; # Capture user input my $input = <STDIN>; # create a character set of input letters my $chars = uc join '', $input =~ /[[:alpha:]]/g; @list_words = grep /[$chars]/, @list_words; }