Search code examples
perlstrict

Assign STDIN to variable in strict mode


The following code works quite as intended when using no strict:

my $file = STDIN;
while (<$file>) {
    print "$_\n";
}

How would be an equal solution using use strict;?


I've tried so far: ${STDIN}, $STDIN, \$STDIN, <STDIN>, and \STDIN, and I am aware that the last two operators (<> and \) have different meanings than I want to use here.

What kind of variable is STDIN anyway? Is it considered a scalar?


Solution

  • my $stdin_h = \*STDIN;
    

    provides the fewest surprises. That is a globref.

    See also perldoc perlref and Typeglobs and Filehandles in perldata:

    Another use for typeglobs is to pass filehandles into a function or to create new filehandles. If you need to use a typeglob to save away a filehandle, do it this way:

    $fh = *STDOUT;
    

    or perhaps as a real reference, like this:

    $fh = \*STDOUT;
    

    STDIN is a bareword. When the argument to a function expecting a file handle, it's equivalent to one of the above \*STDIN, but it's equivalent to "STDIN" the rest of the time (for which use strict 'refs'; throws an error).

    Perl documentation I linked to explains the differences between the various data types involved, but DavidW's brief summary is useful:

    *STDIN is a type glob. This has to do with how Perl stores info in its symbol table. Perl creates an entry in it's symbol table for a particular name, and then creates hash entries for subroutines, file handles, hashes, arrays, and scalars with those names. You can reference this symbol table entry with a * sigil and it's called a type glob. The problem is that there is no sigil for file handles, so you have to refer to them with the type glob. When you open FH ..., FH is a file handle. When you use open my $fh ..., $fh is a type glob ref.