2

I have the following script:

use 5.12.4;
use strict;
use warnings;

say "Enter a functionality:";
while (<>) {
    if (/add/) {
        say "Enter your numbers:";
        my @a = (<>);
        my $sum += $_ for @a;
        say $sum;
    }
}

When I run this program, it prompts:

Enter a functionality:

I enter add and it says:

Enter your numbers:

I enter several numbers on separate lines of input follow by the [ctrl]Z and get the following error:

Use of uninitialized value $sum in say at C:\myperl\Math-Master\math-master.pl l
ine 11, <> line 9.

Why doesn't my code add all of the input? Why does this error come?

2
  • Can you please update the title to make it reflect the actual problem? (Hint: what is the result of $_ for @a in the failing case?) Commented Mar 12, 2012 at 22:50
  • Would setting sum to zero outside the loop fix it? Commented Mar 12, 2012 at 22:55

3 Answers 3

2

You cannot use a postscript loop on a declaration statement. The variable $sum is supposed to be incremented each loop, which it cannot be in the same statement it is being declared. You must first declare it, then assign to it with a postscript loop:

my $sum;
$sum += $_ for @a;

You might consider using List::Util for this, and skipping the temp variable @a. And moving the say inside the while loop:

use List::Util qw(sum);

say "Enter a functionality:";
while (<>) {
    if (/add/) {
        say "Enter your numbers:";
        say "Sum: ", sum(<>);
    }
    say "Enter a functionality:";
}

But that is a bit clunky. Why not:

while (<>) {
    if (/add/) {
        say "Enter your numbers, separated by space: ";
        say "Sum: ", sum(split " ", <>);
    }
}

That way, you do not have to press ctrl-Z (ctrl-D) to stop the input.

Sign up to request clarification or add additional context in comments.

Comments

1

In addition to TLPs answer you might consider using something like this:

chomp(my @a = (<>));

otherwise you would be adding value1\n' and value2\n. This will of course still work, but you might at some point later wonder where all these strange results are coming from...

I've always missed something like foldl() for Perl, but luckily there is List::Util. It adds a bit of syntactic sugar...

use List::Util qw/sum/;
chomp(my @a = (<>));
my $sum = sum @a;
say $sum;

1 Comment

foldl won't win any awards for naming clarity, but from what I can gather, it is a lot like map
0

Here's one way to do it; compare and learn:

use 5.012; # implies 'use strict'
use warnings;

say "Enter a functionality:";
while (<>) {
    if (/add/) {
        say "Enter your numbers:";
        my @nums;
        while (1) {
            my $in = <>; # read one line
            last unless $in =~ m/^\d+$/; # only numbers
            push @nums, $in;
        }
        next unless @nums;
        my $sum;
        $sum += $_ for @nums;
        say $sum;
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.