Saturday March 05, 2005
11:52 AM
Pondering the best idiom: return if this is true...
I'm trying to figure out how best to write this. I want a subroutine to call another subroutine, and if the return value from that subroutine is true, this subroutine should return that value, otherwise continue. Here's some contenders:
eval { return thatroutine() || die };
for (thatroutine()) { return $_ if $_ }
$_ and return $_ for thatroutine();
And then there's a few others that create explicit vars. Any better way to say that?
Maybe returning (Score:2)
Re:Maybe returning (Score:2)
Re:Maybe returning (Score:1)
But if you use
$_instead it will work. Along the same lines,which IMO has a better distribution of emphasis.
And a clever for the sake of clever solution:
Re:Maybe returning (Score:1)
At the very least throw a local in there.
Re:Maybe returning (Score:1)
$_to notice they merely alias – rather than overwrite – it. My bad.last (Score:1)
my $v = thatroutine(); return $v if $v;But another interesting idiom could be this one:
{ return thatroutine() || last }do? (Score:1)
Hmmm, awkward this is one of those things that sounds like it ought to be simple (and clean) to do in Perl, but turns out not do be. I don't like the
evalversion, for some reason: perhaps it gives a misleading impression that you expect the called subrountine is likely to die?How about:
That expresses the logic of what you're up to: return the result either of that function or of running the rest of the code.
I'd probably shunt
Re:do? (Score:2)
sub foo {
return thatroutine() || do {
return thisroutine() || do {
};
};
}
You're already nested once for the subroutine. Then again for the return exception and then possibly
PLAIN ol' text (Score:2)
Re:PLAIN ol' text (Score:1)
<ecode></ecode>tags. Automatically indents the code block for you too (less whitespace on copypaste).Re:PLAIN ol' text (Score:2)
Re:do? (Score:1)
No, nesting is not a problem.
Re:do? (Score:2)
PS use.perl's odd filters have tripped me before. I think they're vestiges from Slashdot that Pudge hasn't turned off.
Re:do? (Score:1)
It does do the same thing – the
thisroutine()call is just the last statement of the firstdo {}block.The construct doesn't have much in common with an
if/elsifchain though. You could write it as one, but it would be very awkward and stilted.Not that I'm a big proponent of this style, mind you.
eval correct? (Score:1)
In your question you wrote:
I don't see that happening with just this line:
The "return" will return the value of "thatroutine()" outside the "eval", but it won't cause the inclosing subroutine to return, if I read the docs correctly. What am I missing?
Anyway, I usually prefer a simple, readable solution, one that doesn't depend on the short-circuit
Re:eval correct? (Score:1)
Sorry, but that's a very poor reason to avoid the short circuit behaviour of boolean ops. Programmers worth their salt must know about it, it such a basic tool, so helpful tool for improving legibility, and so widespread among languages. Without flinching I will go so far as to suggest that those who really cannot figure it out even after explanations, possibly repeated, shouldn't be touching code in the first place.
Clarity shrt (Score:2)
my $whatever = foo();
return $whatever if $whatever;
I know its a lot of repeating $whatever but its at least clear(ish). Contrast with the other ideas:
eval { return thatroutine() || die };
for (thatroutine()) { return $_ if $_ }
$_ and return $_ for t