Reputation: 40319
In Haskell (F#, Ocaml, and others), I can do this:
sign x | x > 0 = 1
| x == 0 = 0
| x < 0 = -1
Which calculates the sign of a given integer.
This can concisely express certain logic flows; I've encountered one of these flows in Perl.
Right now what I am doing is
sub frobnicator
{
my $frob = shift;
return "foo" if $frob eq "Foomaticator";
return "bar" if $frob eq "Barmaticator";
croak("Unable to frob legit value: $frob received");
}
Which feels inexpressive and ugly.
This code has to run on Perl 5.8.8, but of course I am interested in more modern techniques as well.
Upvotes: 1
Views: 179
Reputation: 67918
sub sign {
my $x = shift;
return $x <=> 0;
}
Expressive? If you know what the "spaceship" operator does, yes. If not, not so much. How expressive a piece of perl code feels to you is entirely dependent on your familiarity with perl, I would say.
I must say I've no idea what you are after. To me, the code in your example is perfectly clear and not in the least ugly. There's always alternatives in perl, so how about:
sub frobnicator
{
my $frob = shift;
my %frobs = (
Foomaticator => "foo",
Barmaticator => "bar",
);
return $frobs{$frob} // # If $frob is a defined key, return it
croak("Unable to frob legit value: $frob received");
}
Slightly less precise, but perhaps more friendly to older perl versions is using ||
instead of //
.
Upvotes: 4
Reputation: 7516
For what it's worth, Perl 5.10 or later gives you:
...which would allow:
...
use feature qw( switch say);
use Carp;
sub frobnicator {
my $frob = shift;
given ($frob) {
when ('Foomaticator') {
return q(foo);
}
when ('Barmaticator') {
return q(bar);
}
default {
croak(qq(Unable to frob legit value: $frob received));
}
}
}
Upvotes: 3
Reputation: 6798
Here's one other possible approach, which is still a bit wordy, but perhaps reflects the flow better. (In the book Perl Best Practices, the author suggests mostly avoiding the postfix form of if
because you need to scan all the way to the right to understand what is going on.) You could add parentheses if that helps to highlight the condition.
sub sign
{
my $x = shift;
$x > 0 and return 1;
$x == 0 and return 0;
$x < 0 and return -1;
}
sub frobnicator
{
my $frob = shift;
$frob eq "Foomaticator" and return "foo";
$frob eq "Barmaticator" and return "bar";
croak("Unable to frob legit value: $frob received");
}
Upvotes: 7
Reputation: 35808
You could use the conditional operator:
sub frobnicator {
my $frob = shift;
return $frob eq 'Foomaticator' ? 'foo' :
$frob eq 'Barmaticator' ? 'bar' :
croak("Unable to frob legit value: $frob received");
}
It turns your original example into something like:
sub sign {
my $x = shift;
return $x < 0 ? -1 :
$x > 0 ? 1 :
0 ;
}
Which, y'know, is a little ugly, but it gets the point across :-)
Upvotes: 4