После нескольких лет перерыва в программировании я пытаюсь снова набрать скорость, изучая Perl 6. Эта серия статей задумана как своего рода отчет о прогрессе, демонстрирующий не только то, что я узнал, но и все мои недоразумения и ошибки.
Кто-то скажет, что этот пост был бы лучше, если бы он озаглавлен «Вы не сделали, не так ли?», Потому что пользовательские операторы и их перегрузка обязательно доставят вам проблемы. Однако когда у вас нет проблем, вам это понравится.
Прежде чем объяснять как это сделать, позвольте мне привести несколько сценариев, сосредоточенных вокруг процентов:
- Вы когда-нибудь задумывались, почему нельзя написать «1000 * 20%», чтобы вычислить ответ (200), а нужно написать «1000 * 0,2»?
- Вы когда-нибудь задумывались, почему мы делаем вышеупомянутое, а не более читаемое «20% от 1000»?
- Вы когда-нибудь задумывались, почему мы не можем вычислить «1000 + 20%» и получить ответ 1200? «1000 + (1000 * 0,2)» становится очевидным, когда вы его выучили, но разве не было бы веселее иметь такой ярлык, как «1000 +% 20?
- Вы когда-нибудь задумывались, почему + всегда нужно складывать числа? Разве не было бы забавно, если бы он вычитал и давал вашим коллегам бесконечные часы утомительной отладки? (Ответ, очевидно, отрицательный, но потерпите меня здесь)
- Вы когда-нибудь задумывались, почему не все используют метрическую систему? Как можно быстро преобразовать фунты и стоун (!) В килограммы или градусы Фаренгейта в градусы Цельсия, не прибегая каждый раз к сложным вычислениям?
Что ж, вы не можете сделать ничего из этого и в 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.
Как я часто говорил в этой серии статей: «Мощные штуки!»
Думаю, мои примеры не самые полезные и надежные (как отмечалось выше). Но когда дело доходит до таможенных операторов, это более или менее ступенька в воде.