|We don't bite newbies here... much|
What's wrong with undef?
Currently undef has three different coercions: false, zero, or the empty string. Sometimes those are correct, but not always. Further, by design, it doesn't always emit warnings:
And because it has no precise definition, undef might mean any of a number of things:
In other words, the behavior of undef is overloaded, its meaning is ambiguous and you are not guaranteed to have warnings if you use it incorrectly.
Now think about SQL's NULL value. It's problematic, but no alternative has taken hold for simple reason: its meaning is clear and its behavior is unambiguous. It states quite clearly that 'if I don't have a value, I will treat that value as "unknown" via a set of well-defined rules'.
So, between the ambiguity of Perl's "undef" and the clarity of SQL's NULL, it's probably not surprising that some code could use the latter instead of the former. In fact, I will go further as to assert that the code is often clearer if you do that. Case in point:
I'm sure plenty of you see the bug: what if the employee doesn't have a salary? I've already outlined several reasons above for why the salary might be undefined, not all of which mean "this employee has no salary". So if salary is undefined, you will probably get a warning and you'll have a bug. If threshold is undefined you'll get a warning but you won't have a bug. Fun, eh? So you might rewrite the code like this:
Now that's starting to get ugly. Wouldn't it be if we had simple, clear NULL semantics instead? Now you can, with Unknown::Variables. I explain this idea at length at blogs.perl.org, but it works like this: instead of using "undef", you use "unknown".
There's a lot more to this module than meets the eye, but the idea is that the unknown keyword (well, it acts like a keyword), unlike undef, has clear, well-defined semantics and and predictable behavior.
In the employee salary example above, if an unknown salary returns unknown instead of undef, our code goes back to the original:
Further, you won't generate any warnings because warnings are there to warn you when you're doing something bad. In this case, unknown values are designed to be compared an behave appropriately. And as you can see, our code above becomes much simpler. When used appropriately, unknown values can let your code focus on the problem rather than work around fiddly bits of the language. Any place that you find yourself assigning undef in your code, see what would happen if you put an unknown value there instead.