在 Raku 中是否有用于范围/Num 等的'clamp'方法/子(即 Perl6)?



perl6中是否有'夹具'或等效方法?

例如

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

您可能想探索的另一种tact是使用代理,它允许您在从容器中获取或存储值时定义"挂钩"

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

此特定的limited-num将以最小值初始化,但您也可以在声明

将其设置
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

我不这么认为。所以,也许:

multi clamp ($range, $value) {
  given $range {
    return .max when (($value cmp .max) === More);
    return .min when (($value cmp .min) === Less);
  }
  return $value
} 
my $range = (1.0 .. 9.9);
say $range.&clamp: 15.3; # 9.9
say $range.&clamp: -1.3; # 1
my $range = 'b'..'y';
say $range.&clamp: 'a'; # b
say $range.&clamp: 'z'; # y

MOP允许直接探索P6系统中可用的对象。.^methods是一个特别方便的元模拟物,它适用于大多数内置的对象:

say Range.^methods; # (new excludes-min excludes-max infinite is-int ...

默认情况下,这仅包括Range类中定义的方法,而不是其继承的方法。(要获得所有可以使用say Range.^methods: :all的所有内容。

当我刚尝试时,我发现它也包括许多无用的方法Method+{is-nodal}.new。因此,也可以使用此方法:

say Range.^methods.grep: * !~~ / 'is-nodal' /;

这个网络:

(new excludes-min excludes-max infinite is-int elems iterator
flat reverse first bounds int-bounds fmt ASSIGN-POS roll pick
Capture push append unshift prepend shift pop sum rand in-range
hyper lazy-if lazy item race of is-lazy WHICH Str ACCEPTS perl
Numeric min max BUILDALL)

这就是我用来引导我进入上面解决方案的原因;我有点知道这些方法,但请使用.^methods提醒我。


探索可用内容的另一种方法是DOC,例如官方DOC的Range页面。这使我陷入困境:

ACCEPTS min excludes-min max excludes-max bounds
infinite is-int int-bounds minmax elems list flat
pick roll sum reverse Capture rand

以好奇的方式比较这两个列表,分类和包装:

say
<ACCEPTS ASSIGN-POS BUILDALL Capture Numeric Str WHICH append
 bounds elems excludes-max excludes-min first flat fmt hyper 
 in-range infinite int-bounds is-int is-lazy item iterator
 lazy lazy-if max min new of perl pick pop prepend push
 race rand reverse roll shift sum unshift>.Bag
 ∩
<ACCEPTS Capture bounds elems excludes-max excludes-min flat
 infinite int-bounds is-int list max min minmax pick
 rand reverse roll sum>.Bag

显示:

Bag(ACCEPTS, Capture, bounds, elems, excludes-max, excludes-min,
flat, infinite, int-bounds, is-int, max, min, pick,
rand, reverse, roll, sum)

因此,由于某种原因,listminmaxsum记录为Range方法,但我的.^methods调用未列出。大概它们称为Method+{is-nodal}.new。嗯。

say Range.^lookup('minmax'); # Method+{is-nodal}.new
say Range.^lookup('minmax').name; # minmax

是的。唔。所以我可以写信:

say Range.^methods>>.name.sort;
(ACCEPTS ASSIGN-POS AT-POS BUILDALL Bag BagHash Capture EXISTS-POS
 Mix MixHash Numeric Set SetHash Str WHICH append bounds elems
 excludes-max excludes-min first flat fmt hyper in-range infinite
 int-bounds is-int is-lazy item iterator lazy lazy-if list max min
 minmax new of perl pick pop prepend push race rand reverse roll
 shift sum unshift)

无论如何,希望这很有帮助。

奇怪的是,没有人建议使用augment。诚然,它创造了全球变化,但这可能不是问题。

augment class Range {
   method clamp ($value) { ... }
}

您需要在augment之前使用同一范围的Pragma use MONKEY-TYPING,以便使用它。但是这样,例如,您可以简单地说$range.clamp(5)。它为您节省了一个角色,以雷普的回答,但以(并不重要的)打破预编成本的成本。

相关内容

最新更新