Raku(即 Perl6)中是否有 'clamp' method/sub for ranges/Num 等?
Is there a 'clamp' method/sub for ranges/Num etc in Raku (i.e. Perl6)?
Perl6 中是否有 'clamp' 或等效的方法或子方法?
例如
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
我不这么认为。所以,也许:
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
class 中定义的方法,而不包括它继承的方法。 (要获得所有这些,您可以使用 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
提醒我。
另一种探索可用内容的方法是文档,例如 the official doc's Range
page。这让我感到震惊:
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)
因此,出于某种原因,list
、minmax
和 sum
被记录为 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)
总之,希望对您有所帮助。
您可能想探索的另一个技巧是使用 Proxy,它允许您在从容器
中获取或存储值时定义 "hooks"
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
奇怪的是没有人建议使用 augment
。诚然,它会带来全局变化,但这可能不是问题。
augment class Range {
method clamp ($value) { ... }
}
您需要在 augment
之前的同一范围内使用 pragmause MONKEY-TYPING
才能使用它。但是这样,您可以简单地说 $range.clamp(5)
,例如。它比 raiph 的答案节省了一个字符,但是以破坏预编译为代价(不是微不足道的)。
Perl6 中是否有 'clamp' 或等效的方法或子方法?
例如
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
我不这么认为。所以,也许:
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
class 中定义的方法,而不包括它继承的方法。 (要获得所有这些,您可以使用 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
提醒我。
另一种探索可用内容的方法是文档,例如 the official doc's Range
page。这让我感到震惊:
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)
因此,出于某种原因,list
、minmax
和 sum
被记录为 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)
总之,希望对您有所帮助。
您可能想探索的另一个技巧是使用 Proxy,它允许您在从容器
中获取或存储值时定义 "hooks"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
奇怪的是没有人建议使用 augment
。诚然,它会带来全局变化,但这可能不是问题。
augment class Range {
method clamp ($value) { ... }
}
您需要在 augment
之前的同一范围内使用 pragmause MONKEY-TYPING
才能使用它。但是这样,您可以简单地说 $range.clamp(5)
,例如。它比 raiph 的答案节省了一个字符,但是以破坏预编译为代价(不是微不足道的)。