This has bothered me far more than it should. I quite often end up writing test code that looks like this:
{
my @log = ();
no warnings 'redefine';
*Some::Package::some_func = sub { push @log, [@_] };
sub get_log {
my @old_log = @log;
@log = ();
return @old_log;
}
}
# Then some tests that call subroutines that end up calling some_func.
The idea is to monkeypatch (Perl word of the week) the module I'm testing so I can make sure it calls some_func with the right arguments. For example with TextMate::JumpTo I wanted to test that it was going to invoke/usr/bin/open with the correct args - without actually going through with it and opening something. I didn't want the tests to spew a bunch of random windows into the user's text editor.
None of that is what bothers me. What I find troubling is that get_log is five lines of code just to read and reset the contents of a list. That's really quite upsetting, right?
Today I decided I could endure it no longer (I may be being a little theatrical here) so I spent some time thinking about it. Ideally I'd like to do away with the temporary variable altogether but I can't see a way to do that. Instead I've settled for this:
sub get_log { ( my @got, @log ) = @log }
It's not especially pretty but it's better. That temporary still bugs me though...
Ads by Boggle
Obsessive? Compulsive? Need Help?
No expensive therapy! No painful brain surgery! You can help yourself. Just step away from the keyboard, take a walk, smell the fresh air. YOU ARE FREE!
splice? (Score:1)
I think this will do it:
Just make sure you use it in list context, though.
-- dagolden
Re: (Score:2)
Lovely!
You don't even need the return:
That is a hack of great beauty. Thanks David :)
Re: (Score:1)
-- dagolden
Re: (Score:2)
Re: (Score:1)
A different solution (Score:1)
This isn’t better, but in the spirit of TMTOWTDI and of the
selectidiom fromperldoc -q unbuffer…Or to do away with the array-copy, assuming you have set up with “
my $log = []” instead:The
\@$construction is there to force Perl to make a new copy of the array reference in$log. That way the first list element is a copy of$loginstead of an alias, and therefore unaffected by the overwritdelete Works Too (Score:1)
You can also do this with
deleteinstead ofsplice:It's slightly slower than
splicebut you may consider it's closer to documenting your intent.Re: (Score:2)
Check out Test::Resub (Score:1)