views:

146

answers:

5

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?

+3  A: 

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

David Brown
Does it have a value? Print sdf shows nothing...
Aftershock
@Sinan Ünür: because print takes an indirect object, not because the print call provides list context.
ysth
@ysth noted. I edited my answer to reflect your correction.
Sinan Ünür
+4  A: 

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?

Telemachus
Your last example, `8`, is different than the others in a crucial way.
Sinan Ünür
@Sinan: Yup, it's a number. Explaining that `sdf` is a bareword is helpful, but my focus was on saying that there wasn't anything magical about `sdf`.
Telemachus
@Sinan: thanks for that. I always thought that the empty string *was* undefined. That's my mistake, and I'll correct it.
Telemachus
However, using `strict` will not allow your program to compile if you use `sdf` but, of course, `8` will present no problem. ;-)
Sinan Ünür
+5  A: 

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

Tim
Actually, `0` is `false` but `defined`. Check it: `perl -e 'if (defined 0) { print "True\n" };'`
Telemachus
Sorry, you're absolutely right. :-) Now corrected.
Tim
A: 

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.

EmFi
+10  A: 

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.

Sinan Ünür