The bareword form is, essentially, just historical legacy for backward compatibility. Using a lexical variable is pretty much always The Right Thing To Do in new code.
→ incidentally, $x
is a lexical scalar variable, where FOO
is, as you said, called a bareword
Details/Digression
Just for completeness, as @Joe_Z pointed out in the comments, the lexical filehandle objects are “relatively new,” as a part of the rather major rewrite between Perl 5.005 and 5.6 (they even gained whole orders of magnitude in that version number…).
However, technically, the bareword FOO
(or, e.g. STDIN
) is interpreted in a separate namespace just for filehandles. Since there isn't a sigil (like $ @ % &
) for the filehandle namespace, there are only two ways to reference a filehandle in that namespace:
- You can refer to it in the indirect-object slot of certain functions, like
print
, who will (behind the scenes) infer that a bareword must refer to a filehandle, for historical reasons;
- You can use a typeglob, like
*FOO
, which refers to “anything in any namespace which happens to be bound to the symbol FOO
.
Note that in some languages, like C or Scheme, a single symbol has no type sigils, and so all symbols can be bound only in one way (e.g. one cannot have a variable named printf
and a function named printf
in C … generally), whereas in Perl or (e.g.) Common Lisp, the same symbol foo
can be bound to many different things; the distinction is that Perl actually requires you to use sigils to disambiguate “which foo
you mean” in most contexts. $foo
, @foo
= @foo[ $x .. $y]
, $foo[ $n ]
, %foo
= @foo{ $k1, $k2 }
= $foo{ $k }
, &foo
and the like.
By using barewords as filehandles, though, you lose some abilities:
Significantly, in order to bind them locally or lexically (instead of globally), you need to bind every symbol in every namespace, because there is no sigil available. Thus, my $foo
and my @foo
can live in two different scratchpads (scopes), where perhaps one outlives the other; but my *foo
would include both of these, as well as the filehandle foo
(and potentially other obscure corner-cases, like format
specifiers, although I wouldn't swear to it).
It's also immensely difficult to pass a bareword-style filehandle into a function, and the like.
Basically, barewords inherit all of the downsides of global scope and have none of the advantages of lexical variables.
perldoc perldata
has a nice section on Typeglobs and Filehandles which probably explains these things a bit more clearly, as well. I don't have my copy handy, but I believe the Camel goes into more detail on the subject, as well.