in reply to Summing numbers in a file

Hello pvfki,

When I run your code as written, it works as expected with no errors or warnings. I note that the uninitialized message refers to “line 17” which doesn’t correspond to the code you’ve shown. So I don’t know what the actual problem may be.

A few observations:

Extending the script to process multiple lines just requires a loop:

use warnings 'all'; use strict; use autodie; my $filename = 'numbers.txt'; my $outfile = 'sum.txt'; open(my $in, '<', $filename); open(my $out, '>', $outfile); while (my $numbers = <$in>) { chomp $numbers; my $sum = eval $numbers; print $out $sum, "\n"; } close $out; close $in;

Hope that helps,

Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Replies are listed 'Best First'.
Re^2: Summing numbers in a file
by jcb (Parson) on May 31, 2020 at 01:01 UTC
    the preferred style is to use a scalar variable for a file handle: open(my $N, '<', $filename);

    I will agree with this in the context of a sub that opens a file and closes it before returning, or that returns a file handle. Indeed, I would argue that using a global handle in either of those cases is incorrect. However, I will quibble with this at top-level as in this case: there is no functional difference between the lexical file handles in your example and the traditional global file handles — in both cases, a handle opened at top-level is defined until the end of the script and valid until closed.

    Please correct me if I am somehow misinformed about this.

    PS: Our questioner forgot error handling, so I will point out that open ... or die is an important Perl idiom that is hidden in your example behind the autodie pragma.

      Hello jcb,

      However, I will quibble with this at top-level as in this case: there is no functional difference between the lexical file handles in your example and the traditional global file handles — in both cases, a handle opened at top-level is defined until the end of the script and valid until closed.

      Well, for this particular script, that is quite true. And actually, my advice was only meant as indicating good practice in general. However, it is easy to show that a lexical file handle may be a better choice even at the top level:

      Yes, this is a highly contrived example. But then, why take even remote risks when they can be easily eliminated by the consistent application of good practice?

      Hope that’s of interest,

      Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

        Do I misunderstand, or is the colliding file handle actually Foo::FH in the example? In this example, I would say that the problem is not the use of a global file handle, but the main script placing its code into package Foo and calling frobnicate incorrectly. The use of subroutine prototypes would either make the bug in frobnicate obvious or raise a compile-time error at line 18 when it is called with too many arguments.

        I argue that lexical file handles are a neutral matter of style when they are declared at top-level (which is normally limited to the main script because modules typically provide subs but do not execute code upon loading). The real problem in the contrived example is calling a subroutine with the wrong number of arguments.

        In a case where the file handle is intended to be an "environment parameter" to a subroutine, global file handles are the only option, but please do not actually do that in production code, or at least very clearly document routines that expect certain global file handles to be set up by their callers.

      there is no functional difference between the lexical file handles in your example and the traditional global file handles

      Please see this recent discussion about lexical vs. bareword filehandles. In particular, open(N, "<", $filename); chomp (my $numbers = <M>); only gives warnings, while open(my $N, "<", $filename); chomp (my $numbers = <$M>); is of course a fatal error under strict. Also, bareword filehandles clash with package names.

        That recent discussion involved "pseudo-lexical" file handles using local. I agree that that is a bad idea, but maintain that bareword file handles are reasonable in top-level code. (Modules do not normally contain top-level code.)

        While the typo-catching features of use strict are helpful, you should not be using file handle names that are that easily confused in the first place. In particular, FH is suitable for examples of I/O code, but should not be used in real programs as a global. Global file handles should have meaningful names. For example, I recently wrote code that imports a text-format package manifest into a database; the file is read using a handle named MANIFEST.

        bareword filehandles clash with package names

        I presume that is the origin of the convention of always writing global file handles in all UPPERCASE, since package names are (with few exceptions, like UNIVERSAL) always mixed-case (or lowercase for pragmas) by convention?