Thomson
Thomson

Reputation: 21714

print doesn't recognize barewords as parameter?

In non-strict mode of Perl, barewords could be recognized as string, like below:

$x = hello;
print $x;

But it seems barewords cannot be passed to print directly, like below one doesn't output the string. Why are they different?

print hello;

Upvotes: 2

Views: 72

Answers (3)

melpomene
melpomene

Reputation: 85907

In cases like this, the B::Deparse module can be very helpful:

$ perl -MO=Deparse -e 'print hello;'
print hello $_;
-e syntax OK

As you see, it interprets the identifier as a filehandle and takes the value to be printed from $_.

Upvotes: 6

ikegami
ikegami

Reputation: 386706

An identifier is only a bareword if it has no other meaning.

A word that has no other interpretation in the grammar will be treated as if it were a quoted string. These are known as "barewords".

So, for example, there are no barewords in the following program:

sub f { print STDOUT "f()\n"; }
X: f;

In other circumstances, all of sub, f, print, STDOUT and X could be barewords, but they all have other meanings here. I could add use strict;, and it'll still work fine.

In your code, you used print hello as I used print STDOUT. If an identifier follows print, you are using the print FILEHANDLE LIST syntax of print, where the identifier is the name of a file handle.

Upvotes: 2

Jonathan Leffler
Jonathan Leffler

Reputation: 755094

Barewords should be avoided like the plague they are. Personally, I'll continue to avoid them all the time. They're a relic left over from the wild west days of Perl (circa 1990) and would have been eliminated from the language except for the need to maintain backwards compatibility.

In any case, in that context, it prints $_ to the file handle hello, doesn't it? That's the sort of reason why barewords are worth avoiding. (Compare: print STDERR "Hello\n"; and print STDERR;, and print hello;).

For example:

open hello, ">junk.out";
while (<>)
{
    print STDERR "Hello\n";
    print STDERR;
    print hello;
}

Sample run:

$ perl hello.pl
abc
Hello
abc
def
Hello
def
$ cat junk.out
abc
def
$

In case it isn't clear, I typed one line of abc, which was followed by Hello and abc on standard error; then I typed def, which was followed by Hello and def on standard error. I typed Control-D to indicate EOF, and showed the contents of the file junk.out (which didn't exist before I ran the script). It contained the two lines that I'd typed.

So, don't use barewords — they're confusing. And do use use strict; and use warnings; so that you have less opportunity to be confused.

Upvotes: 3

Related Questions