Perl6 — Перегрузка операторов

в 17:25, , рубрики: perl, perl6, операторы, Программирование, функции, метки: , ,

1. Особенности работы с переменными и литералами в Perl6
2. Perl6 — Операции над переменными, анонимные блоки
3. Perl6 — Условные операторы, циклы
4. Perl6 — Работа с функциями
5. Perl6 — Классы
6. Perl6 — Ввод-вывод, модули
7. Perl6 — Комментарии, пробельные символы, скобки
Однажды я уже писал статью о функциях и об особенностях их использования (№4). Сейчас я хочу рассмотреть одну из их разновидностей — операторов.

Начнем мы, пожалуй, с инфиксных операторов:
Примером инфиксных операторов является оператор '+'

sub infix:<MyNewOperator> (Int $a, Str $b)
{
  return "Call: $a + $b";
}

say 10 MyNewOperator "abc";

В результате мы увидем на экране

Call: 10 + abc

Как видите, мы не ограничены в именах операторов, как это есть в с++ — мы можем добавлять новые или изменять уже существующие, просто поменяв «MyNewOperator» на '+'. В результате мы получим оператор сложения, который вместо приведения типов и склеивания двух строк будет выдавать строку в указанном нами формате.

Так же хотелось бы дополнить, что ради эксперимента я попытался добавить ещё и третий аргумент для инфиксного оператора, и такой оператор даже успешно скомпилировался, но единственный способ вызова такого оператора ничем не отличается от вызова обычной функции:

sub infix:<MyNewOperator> (Int $a, Str $b, $c)
{
  return "Call: $a + $b, $c";
}

say infix:<MyNewOperator>(1, "abc", 5);

Смысла в создании операторов и потом вот такого использования я не вижу, поэтому в дальнейшем отступать от «сигнатуры параметров» я не буду.

Перейдем к следующему типу операторов — префиксному.
Наглядным примером является оператор отрицания логического выражения '!' который мы просто для проверки перегрузим для целых чисел

sub prefix:<!> (Int $a)
{
  return "Call: prefix ! $a";
}

say !1;

Стоит так же заметить, что мы опять же не ограничены именами уже существующих префиксных операторов. Таким образом я даже смог перегрузить оператор '.', что создавало очень необычный вид привызове такого оператора. По этому поводу мне даже вспомнилась где-то прочитанная шуточная фраза «В Perl6 можно будет пергружать операторы, блоки, все, и даже перегружать перегрузку». Шутка шуктой, но префиксный оператор точка как-то уж заставляет задуматься =)

Но пора переходить к других вещам — постфиксным операторам:
Опять же вспомнилась одна статья на тему мелкого шрифта и одного банка:

sub postfix:<*> (Int $a)
{
  return "See $a paragraph in document A";
}

say "We can give you $1_000_000 just for lulz!";
say 1*;

В результате увидим

We can give you $1_000_000 just for lulz!
See 1 paragraph in document A

Опять же касательно всех предидущих типов операторов — по сути мы ограничены в именах операторов только тем, что компилятор должен понять где конец оператора и где начало операнда. Так что не стоит особо изощряться при выборе имени оператора.
И напоследок, пока мы не продолжили, не стоит забывать, что оператор фактически таже функция, поэтому если вы хотите сделать ещё один такой же постфиксный оператор '*' но для строк, то в обоих случаях использования нужно добавить ключевое слово 'multi'.

Но мы всетаки перейдем к следующей категории — перегрузка скобок:

sub circumfix:<(( ))> (Int $a)
{
  return "<$a>";
}

say ((1));

В результате мы получим

<1>

Но не стоит мудрить при выборе «новых» скобок, ибо компилятору все это потом придется разгребать, а из-за вашего вмешательства в список операторов это может оказаться не так просто =)

Однако перейдем к следующему типу — «постфиксные скобки»
Как я ни пытался заставить компилятора перегрузить этого оператора для строки или числа, мне выдавалось сообщение что такого метода просто нету у строк. А примеры которые я находил в интернете были оформлены в виде методов для классов. Из этого я могу предположить, что получиться это сделать только если создам новый класс, поэтому пока что примеры использования попридержим до следующих статей, однако если интересно то можете попытать компилятора на эту тему.

На последок также хотел добавить, что заметил работающую проверку типа возвращаемого значения функцией:

sub Func($a) of Int
{
   return $a;
}

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

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

Автор: WarFair

Источник

Поделиться

* - обязательные к заполнению поля