in reply to Re: Re: Re: Re: Autoboxing: Yes or No?
in thread Autoboxing: Yes or No?

I thought about that, and even experimented with it, but if I use a Null Object I cannot write if( $elt->first_child) {...} anymore, I have to explicitely test for $elt->first_child->is_not_null everywhere, which I don't like, or I have to overload the boolean-ification of the objects, but I am not a fan of overloading, mostly for performance reasons.

I agree that what I ask for is syntactic sugar, but I think it is also quite a natural way to write code, so it might make sense to have this in the language. I like the idea of undef being the null object. Being able to have a false blessed reference would actually be even better, because in this case I would know to which class that flase value belongs.

Replies are listed 'Best First'.
Re(6): Null objects in boolean context
by Ovid (Cardinal) on Jan 01, 2004 at 22:10 UTC

    mirod wrote: If I use a Null Object I cannot write if( $elt->first_child) {...} anymore.

    Ovid begs to differ :)

    package Null::Object; use overload 'bool' => \&bool; my $self; sub new { $self ||= bless {}, shift } sub AUTOLOAD { $self } sub bool { return; } package main; my $null = Null::Object->new; $null->foo->bar->baz; if ($null) { print "We shouldn't be here!"; } else { print "We are false!"; }

    That might need a bit of tuning, but you get the idea.

    Update: I just noticed that you mentioned overload, so my bit of code is not news to you :) On the other hand, if clean null objects is the only benefit of autoboxing, then I again can't see much of a benefit to them. I might also add that null objects should be the exception rather than the rule, thus the performance impact should be minimal (I hope).

    Cheers,
    Ovid

    New address of my CGI Course.

      Ovid this is very interesting... can you explain when you would use this? I've been reading the refactoring book, and like the idea of null objects, but I cannot wrap my brain around your post. Would you put this in the inheritance tree of all objects? Where would one put in the correct behavior for say a Null DBI connection or a Null EmployeeAddress or whatever?

      Thanks for clarifying this for me and all --

      rkg

        The fact that you ask the question indicates that you are too inclined to use inheritance.

        Null objects exist. They make perfect sense on their own. They are an appropriate thing to return when you want to fail to produce a useful object, but do it silently in a chained set of method calls. Just return a Null and let the caller deal with it.

        Think of NULL in a database. It represents missing data. It can appear when you expected any other data type. There aren't (well, except in some vendor extensions) different kinds of NULLs. There don't have to be.

        What are your alternatives? What could have been a simple chain of method calls followed by one if now has to turn into a nested set of if's as you test every method call for success to know if you can make the next. Or you have to wrap it in an eval and complicate your error handling needlessly. The Null is clean, simple, understandable, and that is all that is needed to justify Null's existence.

        No. I would have null objects inherit from something like this (though I might not want the singleton). Because it automatically generates methods, you don't want those created for a real object. However, for a null object, it might be appropriate. For example, let's say that you have a customer and you want to get the sum total of all of his or her orders. Internally, the Customer class might have a method like this:

        sub total_all_orders { my $self = shift; my $total = 0; $total += $order->total foreach $self->orders; return $total; }

        In this case, what if some of those orders are null objects (perhaps this is a design decision that was implemented for cancelled orders), then you could have your Null::Order object:

        package Null::Order; use base 'Null::Object'; sub total { 0 } 1;

        In this case, the null order knows that its total value is zero (this example doesn't make as much sense for Perl because the false value will be converted to zero, but it's perfect for other languages).

        Or you could have a null customer object get returned that has generic information for customers not in your mailing list database and automatically ignores the $customer->add_purchase; method rather than adding it to the database.

        Cheers,
        Ovid

        New address of my CGI Course.

      I might also add that null objects should be the exception rather than the rule, thus the performance impact should be minimal (I hope).

      I haven't benchmarked overloading in a while, but as far as I remember, just using it caused quite a huge performance hit in the rest of the code. IIRC something like 30% slower, with 5.6.0. Things might have changed since then though.