in reply to IF condition with a range

This may be considered bad advice (see: The smartmatch operator is experimental and its behavior is subject to change.), but TIMTOWTDI:
use experimental 'smartmatch'; if (($y-$x) ~~ [-1, 0, +1]) { ... }

Replies are listed 'Best First'.
Re^2: IF condition with a range
by Anonymous Monk on Jul 17, 2018 at 08:23 UTC
    I was wondering, how do you go about in the following scenario?
    * if it is equal, do something
    * if it is equal or within +/- 1 do something else
    Because I think that, if you put these statements in sequential "ifs", then the second one does not find the exact equal matches (they are already greped in the first conditional if).

      You're thinking of something like this:

      if ( it is equal ) { do something; } elsif ( it is equal or close ) { do something else; }

      But you want:

      if ( it is equal ) { do something; } if ( it is equal or close ) { do something else; }

      Or even:

      if ( it is equal or close ) { if ( it is equal ) { do something; } do something else; }
        Aha, so you mean I should have only ifs and not if-elseif. Good, I will try that!

      To build on tobyink's post, remember that it's easy to try things out:

      Updated with the Inf test case suggested by syphilis.

      use warnings; use strict; my @testcases = ( [1,-1], [1,0], [1,1], [1,2], [1,3], [9**9999,9**9999] ); for my $sub (qw/ doit1 doit2 doit3 doit4 /) { print "-----\n"; for my $testcase (@testcases) { print "$sub($testcase->[0], $testcase->[1]):\n"; # for this test only, not recommended otherwise: no strict 'refs'; &{$sub}(@$testcase); } } sub doit1 { my ($x,$y) = @_; if ($x==$y) { print "\tThey are equal, do something\n"; } if (abs($y-$x)<=1) { print "\tThey are within +/- 1, do something else\n"; } } sub doit2 { my ($x,$y) = @_; if ($x==$y) { print "\tThey are equal, do something\n"; } elsif (abs($y-$x)<=1) { print "\tThey are within +/- 1, do something else\n"; } } sub doit3 { my ($x,$y) = @_; if (abs($y-$x)<=1) { print "\tThey are within +/- 1, do something else\n"; } elsif ($x==$y) { print "\tThey are equal, do something\n"; } } sub doit4 { my ($x,$y) = @_; if (abs($y-$x)<=1) { if ($x==$y) { print "\tThey are equal, do something\n"; } print "\tThey are within +/- 1, do something else\n"; } } __END__ ----- doit1(1, -1): doit1(1, 0): They are within +/- 1, do something else doit1(1, 1): They are equal, do something They are within +/- 1, do something else doit1(1, 2): They are within +/- 1, do something else doit1(1, 3): doit1(Inf, Inf): They are equal, do something ----- doit2(1, -1): doit2(1, 0): They are within +/- 1, do something else doit2(1, 1): They are equal, do something doit2(1, 2): They are within +/- 1, do something else doit2(1, 3): doit2(Inf, Inf): They are equal, do something ----- doit3(1, -1): doit3(1, 0): They are within +/- 1, do something else doit3(1, 1): They are within +/- 1, do something else doit3(1, 2): They are within +/- 1, do something else doit3(1, 3): doit3(Inf, Inf): They are equal, do something ----- doit4(1, -1): doit4(1, 0): They are within +/- 1, do something else doit4(1, 1): They are equal, do something They are within +/- 1, do something else doit4(1, 2): They are within +/- 1, do something else doit4(1, 3): doit4(Inf, Inf):

        Frankly with Inf, it's probably a good thing if your code doesn't treat two infinite values as being equal.

        my $x = 6**6**6; # Inf my $y = 7**7**7; # Inf print "equal\n" if $x==$y; # says "equal" even though mathematically +they are not