Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Comment on

( #3333=superdoc: print w/ replies, xml ) Need Help??
In my last meditation I talked about Perl's notion of truth, and mentioned some subtleties. I thought it would be interesting to go into a bit more detail, and describe the complications introduced by overloaded objects.

Update: I've added a <readmore> tag, as suggested by a reaped anonymonk. Sorry if I've violated protocol - I'm new here; feel free to offer friendly advice :-)

The basics

A simple scalar is just an ordinary number or string. There's a special scalar, undef, which is the default value assumed by variables if you don't give them any other value.

Every scalar, simple or otherwise, has a numeric value, a string value and a truth value. You can check them like this:

sub explain { my $val = shift; print "Numeric value = ", 0+$val, "\n"; print "String value = \"$val\"\n"; print "Truth value = ", $val ? "true\n" : "false\n"; }
Here are some examples:
# explain("23skidoo"); Numeric value = 23 String value = "23skidoo" Truth value = true # explain(1_2_3); Numeric value = 123 String value = "123" Truth value = true # explain("1_2_3"); Numeric value = 1 String value = "1_2_3" Truth value = true # explain("00"); Numeric value = 0 String value = "00" Truth value = true # explain("0"); Numeric value = 0 String value = "0" Truth value = false # explain(undef); Numeric value = 0 String value = "" Truth value = false
The rule for determining the boolean value is very simple: if the string value is "" or "0" then it's false; otherwise it's true. Notice that the numeric value is actually irrelevant to truth, except insofar as it can determine the string value. Traditionally in Perl, the string "0 but true" is used as a value which is true, but numerically zero. In fact, that tradition is subtly enshrined in the interpreter: ordinarily, you get a warning when you use a string which contains non-digits as if it were a number:
[robin@robin robin]$ perl -wle 'print 0+"23skidoo"' Argument "23skidoo" isn't numeric in addition (+) at -e line 1. 23
But the string "0 but true" is exempt from the warning:
[robin@robin bits &amp; pieces]$ perl -wle 'print 23+"0 but true"' 23

References and typeglobs

Not all scalars are simple. Some are references. Let's try one:
# explain([1,2,3]); Numeric value = 25616 String value = "ARRAY(0x6410)" Truth value = true
The numeric value is just the memory address used to store the target of the reference. (25616 (base 10) is equal to 6410 (base 16).) That's handy, because it means you can compare two references with $ref1 == $ref2 to find out if they both refer to the same thing.

Some references are blessed, of course. Objects. We'll look at those in the next section. But there's another kind of special scalar - the typeglob. If you did much Perl programming back in the days of Perl 4 you'll certainly remember typeglobs, because they behave like references in some ways and Perl 4 didn't have proper references.

my $foo = *bar; our $bar = "hello\n"; our @bar = ("Hello again!\n"); print $$foo, @$foo; explain($foo);
prints
hello Hello again! Numeric value = 0 String value = "*main::bar" Truth value = true
So the string value of a glob is just the fully-qualified name of the variable(s) it refers to, preceded by a star.

Objects

An object is just a blessed reference:
# explain(bless {}, "SomePackage"); Numeric value = 25616 String value = "SomePackage=HASH(0x6410)" Truth value = true
That's just like an ordinary reference, except that the name of the package it's blessed into is added to the beginning of the string value.

So far, the golden rule for truth has been adhered to strictly. Even the most esoteric special scalars are false if they have a string value of "" or "0", and otherwise they're true. But it gets more complicated than that. You can use overloading to change the default behaviour of an object.

explain(bless {}, "SomePackage"); package SomePackage; use overload '""' => sub {'string value'}; use overload '0+' => sub {23}; use overload 'bool' => sub {""}; use overload fallback => 1;
prints:
Numeric value = 23 String value = "string value" Truth value = false
So you see that each of the three type conversions can be specified separately, and they don't have to be consistent with one another. That's reminiscent of the special variable $!, which gives an error number when used numerically and an error message when used as a string.

You don't have to specify all three. Perl will work out the unspecified conversions based on the conversions that you do specify. Suppose that we delete the '0+' and bool lines from the code above:

Numeric value = 0 String value = "string value" Truth value = true
That's what you ought to expect: Perl is making the same conversions that it would for an ordinary string. Okay, so suppose we specify the string value and the numeric value. What would you expect the truth value to be in this example:
explain(bless {}, "SomePackage"); package SomePackage; use overload '""' => sub {''}; use overload '0+' => sub {23}; use overload fallback => 1;
The answer is surprising. The golden rule is broken!
Numeric value = 23 String value = "" Truth value = true
Even though the string value is "", Perl still considers it to be true! In fact, the numeric value (if it exists) is always used to determine truth when overloading is in effect. (Unless of course an explicit truth value is supplied as well using the 'bool' overload.) This is very strange, and there doesn't appear to be any good reason for it. Unfortunately if we fixed it then existing code would break, so we're probably stuck with it, at least until Perl 6.

Actually, it's even weirder than it looks. What about this?

explain(bless {}, "SomePackage"); package SomePackage; use overload '""' => sub { '' }; use overload '0+' => sub {'00'}; use overload fallback => 1;
Can you predict the truth value? The thing is, the golden rule is being used here, but in a very odd way. The numeric value has a string value of "00", and so it's false!

The truth value is determined by the string value of the numeric value. Wondrous strange!


In reply to What is truth? (Curiosity corner) by robin

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • Outside of code tags, you may need to use entities for some characters:
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?
    Username:
    Password:

    What's my password?
    Create A New User
    Chatterbox?
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others about the Monastery: (9)
    As of 2014-12-21 16:57 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      Is guessing a good strategy for surviving in the IT business?





      Results (106 votes), past polls