После нескольких лет перерыва в программировании я пытаюсь снова набрать скорость, изучая Perl 6. Эта серия статей задумана как своего рода отчет о прогрессе, демонстрирующий не только то, что я узнал, но и все мои недоразумения и ошибки.

Кто-то скажет, что этот пост был бы лучше, если бы он озаглавлен «Вы не сделали, не так ли?», Потому что пользовательские операторы и их перегрузка обязательно доставят вам проблемы. Однако когда у вас нет проблем, вам это понравится.

Прежде чем объяснять как это сделать, позвольте мне привести несколько сценариев, сосредоточенных вокруг процентов:

  1. Вы когда-нибудь задумывались, почему нельзя написать «1000 * 20%», чтобы вычислить ответ (200), а нужно написать «1000 * 0,2»?
  2. Вы когда-нибудь задумывались, почему мы делаем вышеупомянутое, а не более читаемое «20% от 1000»?
  3. Вы когда-нибудь задумывались, почему мы не можем вычислить «1000 + 20%» и получить ответ 1200? «1000 + (1000 * 0,2)» становится очевидным, когда вы его выучили, но разве не было бы веселее иметь такой ярлык, как «1000 +% 20?
  4. Вы когда-нибудь задумывались, почему + всегда нужно складывать числа? Разве не было бы забавно, если бы он вычитал и давал вашим коллегам бесконечные часы утомительной отладки? (Ответ, очевидно, отрицательный, но потерпите меня здесь)
  5. Вы когда-нибудь задумывались, почему не все используют метрическую систему? Как можно быстро преобразовать фунты и стоун (!) В килограммы или градусы Фаренгейта в градусы Цельсия, не прибегая каждый раз к сложным вычислениям?

Что ж, вы не можете сделать ничего из этого и в Perl 6. Хорошая новость заключается в том, что вы можете реализовать свои собственные операторы, чтобы добиться желаемого. Perl 6 дает вам возможность определять собственные операторы и даже перегружать существующие.

Операторы бывают нескольких видов. префикс - ++ $ a (он же return $ a, а затем $ a = $ a + 1); инфикс - 1 + 2; постфикс - $ a ++ (он же $ a = $ a + 1, а затем вернуть $ a); циркумфикс - (1 + 2); postcircumfix - $ a [2] и т. д. Здесь мы сделаем более простые из них и будем придерживаться реальных простых вычислений.

Давайте сделаем самое простое: как научить Perl 6 интерпретировать 20% как 0,2?

sub postfix:<%>($c) {
    return $c * 0.01;
}
# say 20%; (would output 0.2)

Как насчет того, чтобы написать 20% от 500 и получить 100 в качестве ответа? Добавьте это в код выше:

sub infix:<of>($a, $b) {
    return $a * $b;
}
say 20% of 500; # Output: 100

Да, я знаю, что это могло бы сломаться во многих отношениях, если бы ваш код вел себя не так хорошо, как в приведенном выше примере. Но это было больше как введение, чем как пуленепробиваемое решение.

Решение 100 +% 20 = 120 будет выглядеть так:

sub infix:<+%>($a, $b) {
    return $a + ($a * $b%);
}
say 500 +% 20; # Output: 600

И если вы действительно хотите сильно ломать и вообще не иметь смысла, перегрузите +, чтобы он вел себя как -:

sub infix:<+>($a, $b) {
    return $a - $b;
}
say 80 + 20; # Output: 60 (!)

А конверсии…? Определите их!

sub postfix:<lbs>($a) {
    return $a * 0.45359237;
}
sub postfix:<F>($a) {
    return ($a - 32) * 5/9;
}
sub postfix:<stone>($a) {
    return $a * 6.35029318;
}
say 100lbs; # Output: 45.359237..
say 8stone; # Output: 50.80234...
say 85F;    # Output: 29.44444...

И просто чтобы завершить все это, так сказать: вам когда-нибудь нужен был ярлык, чтобы округлить это, как мы, люди, делаем вычисления в своей голове (то есть округляем до ближайшей половины?)

Добавьте это и попробуйте еще раз:

sub prefix:<~>($a) {
    return $a.round(0.5);
}
say ~100lbs; # Output: 45.5
say ~8stone; # Output: 51.
say ~85F;    # Output: 29.5.

Как я часто говорил в этой серии статей: «Мощные штуки!»

Думаю, мои примеры не самые полезные и надежные (как отмечалось выше). Но когда дело доходит до таможенных операторов, это более или менее ступенька в воде.