Re: Re: Re: Autoboxing: Yes or No?
by mirod (Canon) on Jan 01, 2004 at 20:05 UTC
|
OK, so this may not be a "killer app", but one feature of autoboxing can be really a time-saver: methods on undef
I like chaining methods, and often I am only interested in the result of the whole chain. For example when navigating an XML document: $elt->first_child->text or $doc->root->last_child( 'section')->first_child( 'title')->att( 'num'). If one of the calls fails, than I am happy with undef being returned. I just don't like having to test every single method call. Which is often what I have to do, or the program dies when it tries calling a method on undef.
None of the possible alternatives seems to be as convenient as autoboxing undef, the closest in convenience, but I would guess at a higher performance price, being by returning a pre-defined object instead of undef in case of failure and overloading the boolean-ification of the object.
| [reply] [d/l] [select] |
|
|
| [reply] |
|
|
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.
| [reply] [d/l] [select] |
|
|
|
|
|
|
|
|
|
I think this is a problem best left unaddressed. In general OO the Law of Demeter forbids such deep hierarchy navigation constructs.
Now, manipulating XML (or other document) structures is a very specific case, and not all the common OO rules necessarily apply. However, I'd argue that this means you should rather be using a language addressed at this specific problem domain. Which in this case does exist and should be obvious: XPath. Indeed, something like this behaves exactly the way you specified:
# LibXML lingo; XPath expr is off the cuff, untested
$doc->findvalue('/section[last()]/title[1]/@num');
All that said, even methods on undef would not really solve the issue, just sweep it under the rug. Doing this well and cleanly in Perl would require something along the lines of
$doc->root(sub {
$_->last_child( 'section', sub {
$_->first_child( 'title', sub {
$_->att( 'num')
})
})
});
In summary, you will not be able to solve this satisfactorily and concisely in a language without continuations. Which isn't so bad, because this particular problem is likely better left unsolved.
Makeshifts last the longest.
| [reply] [d/l] [select] |
|
|
Aristotle wrote: I think this is a problem best left unaddressed. In general OO the Law of Demeter forbids such deep hierarchy navigation constructs.
I am wondering if I missed what you were trying to say. The Law of Demeter lets us know that this is bad:
my $company = $sales_rep
->office
->division
->company;
This enforces a class heirarchy which becomes inflexible since the user's code must now know the class heirarchy (bad!) and this makes changing the heirarchy more difficult. However, there's nothing wrong with this:
$sales_rep
->set_title($title)
->set_office($office)
->set_something_else($foo);
In this case, there is no enforcement of a particular class heirarchy and you therefore aren't bound by one. With mirod's example, I think we have the same thing:
$doc
->root
->last_child('section')
->first_child('title')
->att('num')'
While these are accessors and not mutators, we still appear to only be dealing with only one class and are less concerned with restructuring things. We have a published interface that only one class needs to maintain, whereas with my first example, we appear to have the various classes needing to know about the published interfaces of other classes and this greatly compounds the problem, thus increasing maintenance costs.
If I am misunderstanding the situation (or your objection), please let me know.
| [reply] [d/l] [select] |
|
|
|
|
I agree with using XPath... if it's available. It is now available for XML::Twig but that's quite recent. Also in this case I used only accessors, but as pointed by ovid, I could have used setters or other methods.
And yes, it mostly "sweeps the issue under the rug", the same way Perl itself sweeps under the rug the fact that $ sometimes matches just the end of the string, and sometimes matches a line return and the end of the string. It might not always be the correct thing to do, it is just natural and convenient when you don't have to be too strict.
I really like ovid's comparison of the null object to the relational NULL BTW: sometimes you don't want the absence of some data to stop you, and you don't want to (and you should not have to) write a special case to handle it.
| [reply] |
|
|
Could you get around that by just doing eval{ $child->parent->grandparent->bar()} if($@){} And check $@ for 'method on undef' or whatever the exact string is?
| [reply] [d/l] |
|
|
| [reply] |
|
|
eval {
$some->big->chain->of->calls
}
die $@ if($@
&& $@ =~ /\^Can't call method .* on an undefined/)
Add sugar to your taste
(Or Perl6's undef but ?something?;) | [reply] [d/l] |
|
|
| [reply] |
|
|