Search code examples
rakuclamp

Is there a 'clamp' method/sub for ranges/Num etc in Raku (i.e. Perl6)?


Is there a 'clamp' or equivalent method or sub in Perl6?

eg

my $range= (1.0 .. 9.9)
my $val=15.3;

my $clamped=$range.clamp($val);
# $clamped would be 9.9

$val= -1.3;
$clamped=$range.clamp($val);
# $clamped would be 1.0

Solution

  • Another tact you might like to explore is using a Proxy, which allows you to define "hooks" when fetching or storing a value from a container

    sub limited-num(Range $range) is rw {
        my ($min, $max) = $range.minmax;
        my Numeric $store = $min;
        Proxy.new(
            FETCH => method () { $store },
            STORE => method ($new) {
                $store = max($min, min($max, $new));
            }
        )
    }
    
    # Note the use of binding operator `:=`
    my $ln := limited-num(1.0 .. 9.9);
    say $ln;     # OUTPUT: 1
    
    $ln += 4.2;  
    say $ln;     # OUTPUT: 5.2
    
    $ln += 100;  
    say $ln;     # OUTPUT: 9.9
    
    $ln -= 50;   
    say $ln;     # OUTPUT: 1
    
    $ln = 0;     
    say $ln;     # OUTPUT: 1
    

    This particular limited-num will initialise with it's min value, but you can also set it at declaration

    my $ln1 := limited-num(1.0 .. 9.9) = 5.5;
    say $ln1;    # OUTPUT 5.5;
    
    my $ln2 := limited-num(1.0 .. 9.9) = 1000;
    say $ln2;    # OUTPUT 9.9