Есть ли в Perl6 метод / зажим 'sub' для диапазонов / Num и т. Д. - PullRequest
7 голосов
/ 20 марта 2019

Есть ли в Perl6 «зажим» или эквивалентный метод или субтитр?

Ответы [ 2 ]

9 голосов
/ 20 марта 2019

Еще один такт, который вы хотели бы изучить, - это использование Proxy , которое позволяет вам определять «ловушки» при извлечении или сохранении значения из контейнера

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
5 голосов
/ 20 марта 2019

Я так не думаю.Итак, возможно:

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, чтобы напомнить мне.


Еще один способ изучить то, что доступно, это документ, например, официальный документ 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)

Итакпо некоторым причинам 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)

Во всяком случае, надеюсь, что это полезно.

...