This module provides you with two new keywords, unknown and is_unknown. From the point of view of logic, the is often an improvement over undef values. Consider the following code, used to give underpaid employees a pay raise:

Note: That's actually problematic because an unknown value doesn't mean a non-existent value, just an unknown one, so the value might be equal, but we don't know it. From the standpoint of pure logic, it's wrong, but it's so awfully convenient that we've allowed it. We might revisit this.

This is not a bug because we cannot positively state whether $value is true or defined, thus meaning that ||= and //= must both return unknown values. To fix this, either assign a value when you declare the variable:

This module is an attempt to squeeze three-value logic into Perl, even though it's a bit of an awkward fit. Further, there are several reasons why something could fail to have a value, including "not yet known" (what this module is about), "not applicable" (something the programmer handles explicitly), "privileged" (you can't have the credit card number), an "empty set" (this is not zero), and so on. Empty sets are always equal to one another (there is, technically, only one empty set), but which of the others should be comparable?

<undef == undef> throws a warning, but allows the program to continue. Is throws the warning because it can't know if this comparison is appropriate or not. For the case of unknown values, we explicitly know the comparison is not appropriate and thus we don't allow it.

Should the compare() function return an unknown which returns false in booleans? That might be useful when chaining boolean tests.

More importantly, should every unknown return a sequentially different unknown and thus allow me to say that an unknown is equal to itself but not equal to other unknowns? this means that we could do this:

So an unknown sometimes equals unknowns and sometimes doesn't. It only matches an unknown if it's itself. On the surface this actually seems to be correct, except that we then have this:

if ( ( 6 != $value1 ) == ( 7 != $value1 ) ) {
... always false
}

That has to be false because 6 != $value1must return a unknown and 7 != $value1 should return a different unknown and their cascaded unknown value should fail. However, the following must be true:

if ( ( 6 != $value1 ) == ( 6 != $value1 ) ) {
... always true!
}

Because 6 != $value1 should always return the same unknown. Here's why. We assume, for the sake of argument, that the unknown $value1 has a value, but we don't know it. Let's say that value is 4. The above reduces to this:

if ( ( 6 != 4 ) == ( 6 != 4 ) ) {

Since 6 != 4 is true, we get this:

if ( 1 == 1 ) {

Ah, but what if <$value1>'s hidden value was actually 6? Then we get this:

if ( ( 6 != 6 ) == ( 6 != 6 ) ) {

Since 6 != 6 is false, we get this:

if ( 0 == 0 ) {

In other words, there's a lot of interesting things we could do, but this would likely involve a fair amount of work breaking out the code for each and every operator and ensuring that it's handled correctly.

Of course, this would eat up both memory and performance and certainly be filled with fiddly bugs.