Why does defined sdf return true in this Perl exam

2019-07-01 15:40发布

问题:

I tried this example in Perl. Can someone explain why is it true?

  if (defined sdf)  {   print "true";  }

It prints true.

sdf could be any name.

In addition, if there is sdf function defined and it returns 0, then it does not print anything.

print (sdf); does not print sdf string but

if (sdf eq "sdf")
{
 print "true";
}

prints true.

The related question remains if sdf is a string. What is it not printed by print?

回答1:

sdf is a bareword.

perl -Mstrict -e "print qq{defined\n} if defined sdf"
Bareword "sdf" not allowed while "strict subs" in use at -e line 1.
Execution of -e aborted due to compilation errors.

For more fun, try

perl -Mstrict -e "print sdf => qq{\n}"

See Strictly speaking about use strict:

The subs aspect of use strict disables the interpretation of ``bare words'' as text strings. By default, a Perl identifier (a sequence of letters, digits, and underscores, not starting with a digit unless it is completely numeric) that is not otherwise a built-in keyword or previously seen subroutine definition is treated as a quoted text string:

@daynames = (sun, mon, tue, wed, thu, fri, sat);

However, this is considered to be a dangerous practice, because obscure bugs may result:

@monthnames = (jan, feb, mar, apr, may, jun,
               jul, aug, sep, oct, nov, dec);

Can you spot the bug? Yes, the 10th entry is not the string 'oct', but rather an invocation of the built-in oct() function, returning the numeric equivalent of the default $_ treated as an octal number.

Corrected: (thanks @ysth)

E:\Home> perl -we "print sdf"
Unquoted string "sdf" may clash with future reserved word at -e line 1.
Name "main::sdf" used only once: possible typo at -e line 1.
print() on unopened filehandle sdf at -e line 1.

If a bareword is supplied to print in the indirect object slot, it is taken as a filehandle to print to. Since no other arguments are supplied, print defaults to printing $_ to filehandle sdf. Since sdf has not been opened, it fails. If you run this without warnings, you do not see any output. Note also:

E:\Home> perl -MO=Deparse -e "print sdf"
print sdf $_;

as confirmation of this observation. Note also:

E:\Home> perl -e "print asdfg, sadjkfsh"
No comma allowed after filehandle at -e line 1.
E:\Home> perl -e "print asdfg => sadjkfsh"
asdfgsadjkfsh

The latter prints both strings because => automatically quotes strings on the LHS if they consist solely of 'word' characters, removing the filehandle interpretation of the first argument.

All of these examples show that using barewords leads to many surprises. You should use strict to avoid such cases.



回答2:

This is a "bareword". If it is allowed, it has the value of "sdf", and is therefore not undefined.



回答3:

The example isn't special:

telemachus ~ $ perl -e 'if (defined sdf) { print "True\n" };'
True
telemachus ~ $ perl -e 'if (defined abc) { print "True\n" };'
True
telemachus ~ $ perl -e 'if (defined ccc) { print "True\n" };'
True
telemachus ~ $ perl -e 'if (defined 8) { print "True\n" };'
True

None of those is equivalent to undef which is what defined checks for.

You might want to check out this article on truth in Perl: What is Truth?



回答4:

defined returns true if the expression has a value other than the undefined value.



回答5:

the defined function returns true unless the value passed in the argument is undefined. This is useful from distinguishing a variable containing 0 or "" from a variable that just winked into existence.