Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Style Question: Throwaway Objects

by seattlejohn (Deacon)
on Dec 09, 2002 at 00:14 UTC ( [id://218410]=perlmeditation: print w/replies, xml ) Need Help??

Hi all,

I've got a program that instantiates a Spreadsheet::ParseExcel object, immediately calls a method to parse a spreadsheet, and never needs to use the object again. I had originally written the relevant code something like this:

my $parser = Spreadsheet::ParseExcel->new(); my $book = $parser->Parse($filename);

But since the only place I end up using the object I constructed is in that second line, I found myself wondering if it wouldn't be cleaner to simply do this: my $book = Spreadsheet::ParseExcel->new()->Parse($filename);

I'm wondering if other monks approve of this condensed form, or if it seems awkward or might have undesirable side effects I haven't considered. Thoughts?

        $perlmonks{seattlejohn} = 'John Clyman';

Replies are listed 'Best First'.
Re: Style Question: Throwaway Objects
by BrowserUk (Patriarch) on Dec 09, 2002 at 00:35 UTC

    One risk you run with the condensed form is that if you get a failure, you make it harder to debug the cause. That is to say, if your code is much more than a throw away, you probably should be doing something like

    my $parser = Spreadsheet::ParseExcel->new() or die "Some error text"; my $book = $parser->Parse($filename) or die "Some error text";

    Of course it may be that there is no chance that the first step will fail if the preceding use Spreadsheet::ParseExcel; statement succeeded, but that will depend on the module. If this is the case, then I would probably do away with the intermediary and go with

    my $book = Spreadsheet::ParseExcel->new()->Parse($filename) or die "Couldn't parse file: $filename";

    Unless that module Carps or Croaks under these circumstances.


    Okay you lot, get your wings on the left, halos on the right. It's one size fits all, and "No!", you can't have a different color.
    Pick up your cloud down the end and "Yes" if you get allocated a grey one they are a bit damp under foot, but someone has to get them.
    Get used to the wings fast cos its an 8 hour day...unless the Govenor calls for a cyclone or hurricane, in which case 16 hour shifts are mandatory.
    Just be grateful that you arrived just as the tornado season finished. Them buggers are real work.

      Of course, if one wants to avoid naming an extra variable, a do BLOCK is the logical choice and doesn't even necessarily reduce readability:
      my $book = do { Spreadsheet::ParseExcel->new() or die "Some error text" } ->Parse($filename) or die "Some error text";

      Makeshifts last the longest.

        If you formatted that as

        my $book = do { Spreadsheet::ParseExcel->new() or die "Some error text" }->Parse($filename) or die "Some error text";

        I might agree with you :^).


        Okay you lot, get your wings on the left, halos on the right. It's one size fits all, and "No!", you can't have a different color.
        Pick up your cloud down the end and "Yes" if you get allocated a grey one they are a bit damp under foot, but someone has to get them.
        Get used to the wings fast cos its an 8 hour day...unless the Govenor calls for a cyclone or hurricane, in which case 16 hour shifts are mandatory.
        Just be grateful that you arrived just as the tornado season finished. Them buggers are real work.

      Ah, good point about testing for an error in the constructor. I've got an or die... clause following the Parse call in the actual code, though I omitted it for simplicity's sake in the example above. But I suppose you're right that if Spreadsheet::ParseExcel->new() returned an invalid object reference for some reason, then that would bungle up the method call and generate an error that might not be very obvious.

              $perlmonks{seattlejohn} = 'John Clyman';

Re: Style Question: Throwaway Objects
by dws (Chancellor) on Dec 09, 2002 at 00:31 UTC
    Writing my $book = Spreadsheet::ParseExcel->new()->Parse($filename); is equivalent to writing
    my $parser = Spreadsheet::ParseExcel->new(); my $book = $parser->Parse($filename); undef $parser;
    I'd go with whichever you think reads better, or the original snippet. (I favor the original snippet, on the assumption that keeping the ParseExcel object alive for the duration of the scope has little or no measurable impact on performance or memory use.) BrowserUK nails this one. Keep the statements separate, so that you can error check them separately. If you're concerned about memory, you can always undef $parser;

      Just to nitpick: you're leaving a lexical $parser around that the condensed form doesn't, so it is actually equivalent to
      my $book; { my $parser = Spreadsheet::ParseExcel->new() $book = $parser->Parse($filename); }
      or, as I'd prefer,
      my $book = do { my $parser = Spreadsheet::ParseExcel->new() $parser->Parse($filename); };
      logically followed by
      my $book = do { my $parser = Spreadsheet::ParseExcel->new() $parser }->Parse($filename);
      which is (and here's the important step) obviously equivalent to my $book = do { Spreadsheet::ParseExcel->new() }->Parse($filename); which is trivially equivalent to my $book = Spreadsheet::ParseExcel->new()->Parse($filename); Tightly scoping with a block instead is generally better practice. The garbage collector will clean up after you without any extra effort on your side anyway.

      Makeshifts last the longest.

        Just to nitpick: you're leaving a lexical $parser around that the condensed form doesn't

        Well, yes. But compared to turning a very readable

        my $parser = Spreadsheet::ParseExcel->new() my $book = $parser->Parse($filename);
        into a double-take inducing   my $book = do { Spreadsheet::ParseExcel->new() }->Parse($filename); leaving a lexical around is a minor sin. When I have to choose between various sins, I'll go with the one that's readable.

      Thanks for the response, and just for the record: I'm not *that* concerned about memory. I was just reviewing some code I'd written previously looking for refactoring opportunities, redundant redundancies, unnecessary verbosity, and general housekeeping opportunities... and I found myself wondering if there would be any upside (or downside) to combining those two lines into one.

      I tend to be a stickler for testing and reporting on errors, and BrowserUk has convinced me that error-reporting alone is a good reason to keep those lines separate.

      Again, thanks!

              $perlmonks{seattlejohn} = 'John Clyman';

Re: Style Question: Throwaway Objects
by demerphq (Chancellor) on Dec 09, 2002 at 12:28 UTC
    Well. I think for things like this you need to be flexible. In this particular case, the error catching that BrowserUk and others discuss is particularly important as (fwict) Spreadsheet::ParseExcel uses OLE to talk to the Excel com server object and that this type of code is vulnerable to error outside of the scope of your own code. However your question

    I'm wondering if other monks approve of this condensed form, or if it seems awkward or might have undesirable side effects I haven't considered. Thoughts?

    if considered from the POV of using pure perl objects who do not return errors via the functional interface it is not at all a bad thing. It has for instance been the recommended way of using Data::Dumper for the past ages...

    my $dump=Data::Dumper->new([$foo,$bar]) ->Names([qw(foo bar)]) ->Purity(0) ->Terse(1) ->Useqq(1) ->Indent(0) ->Dump();
    In fact this touches on what is one of my little pet peeves about Perl. For all intents and purposes this style (which has to be deliberately enabled by the class author) is a replacment for a with statement, without the error catching opportunities of a proper with block. If a real with() was available I would personally say to avoid this style and use the with, but absent that construct I see no reason for the style not to be utilised when error catching through return value isnt a serious issue (such as when using dumper).

    For the paranoid, wrapping this construct in an eval{} would provide a clean way to catch the errors.

    --- demerphq
    my friends call me, usually because I'm late....

        Interestingly it has been pointed out to me that for() can be used as a with, but it doesnt quite do it for me...
        for ($some->{complex}[$object]{that}{we}[$need]{to}[$use]) { $_->foo; $_->bar; }
        And a proper with construct allows the compiler opportunities to optimize far beyond what any other solution allows as it explicitly states that the object will be immutable for the duration of the with. *sigh*

        :-)

        --- demerphq
        my friends call me, usually because I'm late....

Re: Style Question: Throwaway Objects
by Abigail-II (Bishop) on Dec 09, 2002 at 17:27 UTC
    Quite common in Tk code actually:
    $parent -> Button (-text => 'Quit', -command => sub {Tk::exit}) -> pack;

    Both the Button method and the pack method return an object (the same one actually), but if you don't need to use the widget anymore, it's often discarded.

    Abigail

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://218410]
Approved by mjeaton
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (4)
As of 2024-04-25 17:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found