Ben Morrow said:
Quoth (e-mail address removed):
[...]
my $result = do {
if ($i % 2 == 0) { 'even' }
elsif ($i % 3 == 0) { 'divisible by 3' }
elsif ($i % 5 == 0) { 'divisible by 5' }
else { 'just wrong' }
};
Is there a clever way in Perl 5 to metaphorically return early with a
value?
[...]
The other thing that works, and it is in fact documented though I had no
idea until I just looked, is to return from an eval {}:
my $result = eval {
$_ % 2 == 0 and return "even";
$_ % 3 == 0 and return "divisible by three";
return "just wrong";
};
I'm not sure it's got much to recommend it over
my $result = sub {
$_ % 2 == 0 and return "even";
return "odd";
}->();
though,
The first is using a language construct according to its intended
purpose. The second is abusing a language construct in order to
emulate the first 'somehow'. That alone should be sufficient to avoid
it. In addition to that, it needs more test because the mock
subroutine created for this purpose also needs to be invoked and -
depending on whether the compiler special-cases this so that people
can indulge their passion for the bizarre[*] - it is probably also
less efficient.
I infer that "first" means the eval example and "second" means the sub
example.
The notion of "abusing a language construct" in Perl is already a
problematic notion. Perl is the polyperverted abuse bottom of
languages.
The doc for eval says "This form is typically used to trap exceptions
more efficiently than the first (see below), while also providing the
benefit of checking the code within BLOCK at compile time." So using
eval just to be able to return is not its "intended purpose".
In fact, the eval version is the one that needs the testing, not the
sub. eval traps fatal terminations, and just about anything can
die(). In this simple case, I think you'd need "use warnings FATAL =>
'numeric';". More realistic examples can die much easier. So you
can't just replace do{...} with eval{...}; you'd have to add proper
error checking and we've recently had a discussion about the edge
cases to worry about.
sub{...}, on the other hand, *is* a straightforward substitution.
Also, for people like me who are used to Lisp and similar languages
that make much more use of small functions created all over, it's a
natural idiom. Also, it has an argument list, so some complexity
could be encapsulated there, allowing the body of the text to refer to
$_[2] or assigning the argument to a variable as one likes.
I don't know how to test efficiency. I've seen a few uses of some
module to run a construct a number of times and report on the time,
but I apparently wasn't using the correct search terms at CPAN.