Re: Passing logical operators on as content of scalar
by Eily (Monsignor) on Feb 08, 2018 at 17:14 UTC
|
Well, you might not do much better than that easily actually. The Dispatch table design pattern can help (you associate functions with some keys) which gives a basic example like that:
use strict;
use warnings;
use feature 'say';
my %operators = (
'>' => sub { $_[0] > $_[1] },
'==' => sub { $_[0] == $_[1] });
sub test
{
my ($op, $left, $right) = @_;
die "Unknown operator: $op" unless exists $operators{$op};
say "$left $op $right" and return if $operators{$op}($left, $right);
say "$right $op $left" if $operators{$op}($right, $left);
}
test "==", 1, 1;
test ">", 2, 3;
test ">", 4, 5;
test "<", 6, 7;
__DATA__
1 == 1
3 > 2
5 > 4
Unknown operator: < at pm_1208722.pl line 12.
But if you want your own sentence to be written you'll need a more complex structure where for each key you have either several functions (one to compare, one to print) or a function and a template or something. I don't have the time to go any further than that at the moment though ^^". | [reply] [d/l] |
Re: Passing logical operators on as content of scalar
by choroba (Cardinal) on Feb 08, 2018 at 19:10 UTC
|
You might be interested in the comparison operator <=>:
#!/usr/bin/perl
use warnings;
use strict;
my $number1 = '2011';
my $number2 = '2011';
my $selectioncriterium = '==';
sub smaller { "$_[0] is smaller than $_[1]" }
my %dispatch = (
0 => sub { "$_[0] equals $_[1]" },
1 => sub { smaller($_[1], $_[0]) },
-1 => sub { smaller($_[0], $_[1]) },
);
print $dispatch{ $number1 <=> $number2 }->($number1, $number2), "\n";
($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord
}map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
| [reply] [d/l] [select] |
|
print $number1, " is ",
("less than", "equal to", "greater than")[($number1 <=> $number2)
++ 1],
" ", $number2, "\n";
| [reply] [d/l] |
|
print $number1, " is ",
("equal to", "greater than", "less than")[$number1 <=> $number2],
" ", $number2, "\n";
No need to add one :)
| [reply] [d/l] |
|
|
Re: Passing logical operators on as content of scalar
by Marshall (Canon) on Feb 08, 2018 at 19:37 UTC
|
Your code as written is easy to understand at a glance. However, I think you are missing a case in the '<' situation, where $number1 is equal
to $number2?
I liked the post by Eily++. If I went that way, I likely would go further by incorporating the result of $number1 <=> $number2 into the hash key. That way there are no "if" statements at all in the calling code. Maybe resulting in a table like this?:
my $dispatch = {"< -1" => "num1 less than num2",
"< 0" => \&actionX,
# blah...blah 6 or 9 entries to cover all cases, <, >,
+== times 3
};
In your "==" case, the dispatch action for $num1<$num2 and $num1>$num2 would be the same.
Note: I would have to read the spec carefully on the spaceship operator. Instead of it returning -1,0,1 which is what it actually does, it might be spec'd as only negative number,0,positive number. I would allow whatever the spec says is allowed (convert to -1,0,1 so that hash lookup works no matter what exact spaceship implementation is).
However having said that, the code structure that you have is easy to understand and it will execute very quickly (faster than a dispatch table). It took me a bit more "brainpower" to understand the Eily code whereas I understood your code at a glance. I wouldn't be overly concerned about "wordiness". If the pattern shown in your code repeats often elsewhere in the code, then the "understanding overhead" associated with the dispatch table is perhaps worth it. Simple, albeit it wordy code is often a good way to go. It is also possible that I might implement the three cases <,>,== with the same if logic (no special handling of ==). That would make the code even more wordy, but more "regular". Coding is part art and part science - lot's of ways to do things. | [reply] [d/l] [select] |
Re: Passing logical operators on as content of scalar
by Lotus1 (Vicar) on Feb 08, 2018 at 17:30 UTC
|
elsif ($selectioncriterium eq '=='){
print "$number1 is ", $number1 == $number2 ? '' : 'not ', "equal t
+o $number2\n";
}
For <, >, == it isn't as easy since there are three choices. | [reply] [d/l] |
Re: Passing logical operators on as content of scalar
by Laurent_R (Canon) on Feb 08, 2018 at 22:05 UTC
|
Really not sure whether this is any better, but you could use (string) eval, as shown here under the debugger:
DB<1> $number1 = 2011;
DB<2> $number2 = 2011;
DB<3> $selectioncriterium = '=='
DB<4> print "number1 is ", eval "$number1 $selectioncriterium $num
+ber2" ? "" : "not ", "equal to $number2\n";
number1 is equal to 2011
DB<5> print "number1 is ", eval "$number1 $selectioncriterium 7842
+"? "" : "not ", "equal to 7842\n";
number1 is not equal to 7842
| [reply] [d/l] |
|
Thanks for all the help and suggestions. Everything is valuable and has enlightened me.
| [reply] |