Pull to refresh

Perl6 — Работа с функциями

Reading time3 min
Views4.4K
1. Особенности работы с переменными и литералами в Perl6
2. Perl6 — Операции над переменными, анонимные блоки
3. Perl6 — Условные операторы, циклы

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



В Perl6 функции объявляются конструкцией
sub SubName($a, $r, $g, $s)
 {
     //SomeWork
 }

Имеется возможность указывать типы получаемых параметров
sub SubName(Int $a)
 { SomeWork(); }

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

Вызов функции происходит с помощью конструкций
f(10, True, "str", {say "closure";});
f 20, False, "aaa", 9.999;


Так же как и в C++ мы можем делать перегрузку функций, однако для каждой функции необходимо будет добавлять слово 'multi':
multi sub f(Int $a) {say 'Int';};
multi sub f(Str $a) {say 'Str';};
f("string"); f(100500);

В результате будет выведено на экран:
Str
Int


Для указания области видимости функций используются слова my и our — соответственно видимость в той области где функция была объявлена и глобальная область видимости.
Можно указывать тип значения, возвращаемого функцией:
my Int sub func($a)
 {return $a+1;}

В случае не совпадения указанного при объявлении типа и типа возвращаемого значения во время работы, скрипт будет остановлен с ошибкой о несоответствии типов.
Параметрам функции можно дополнительно указывать, можно ли изменять эти параметры внутри функции:
sub f($a is rw)
 {
     $a*=10;
 }
my $z = 5;
f($z);
say $z;

В результате будет выведено число 50
Так же в синопсах указано, что функция может возвращать lvalue значение:
my $b = 10;
sub f() is rw
 {
     return $b;
 }
f() = 5;
say $b;

В результате на экране должно будет выведено число 5, однако в последней версии (12.09) возможность исользования lvalue значений ещё не готова, и в моем случае выдавалась ошибка при компиляции.
В Perl6 появилась возможность использования именованных параметров:
my sub func(:$name1, :$name2, :$name3)
 {
     say $name1, ' ', $name2, ' ', $name3;
 }
my $a = 10;
func :name2<text2>, :name1<1+2+$a>, name3=>$a;
my %hash = {name3=>'text3', name2=>'text2', name1=>'text1'};
func |%hash;

В результате на экране будет выведено:
1+2+$a text2 10
text1 text2 text3

Если в качестве параметра передавать не |%hash а просто %hash, то тогда функция будет принимать его как позиционный аргумент — в нашем случае у функции нет позиционных элементов, поэтому работа скрипта будет завершена с ошибкой.
Так же для указания именованного аргумента можно использовать конструкцию :arg($value). Разница между этим вариантом и :arg<$value> в том, что во втором случае значение переменной не будет подставляться, и в итоге в первом случае мы получаем значение переменной $value, а во втором случае получаем строку '$value'.
В дополнении можно использовать необязательные параметры:
sub HaveArgument($arg?)
 {
     if $arg.defined
      {
          say 'yes';
      }
     else
      {
          say 'no';
      }
 }
HaveArgument;
HaveArgument 10;

В результате получим строки
no
yes

Для создания функций с переменным количеством аргументов, как было в perl5, можно воспользоваться конструкцией:
sub Counter(*@arg)
 {
     say @arg.elems;
 }
Counter(1, 2, 3);
Counter;

В результате будет выведено два числа: 3 и 0
Перед *@ args можно указывать позиционные элементы:
sub Counter($a, *@arg)
 {...}

Функция MAIN:
В Perl6 появилась возможность создания функции MAIN, как на подобии C++, однако, есть несколько отличий. Нарпимер вне тела функции можно делать вызовы других функций, и эти вызовы будут совершены раньше чем начнет выполняться функция MAIN:
sub MAIN()
 {
     say "MAIN!";
     say "Hello!";
 } 
say "123!";

В результате на экране мы увидим строки
123!
MAIN!
Hello!

Так же для функции MAIN можно задавать входные параметры, которые будут являться обязательными параметрами при вызове скрипта на исполнение:
Если содержимое скрипта:
sub MAIN($arg1, $arg2)
 {
     say "MAIN!";
     say $arg1, ' ', $arg2;
 }
say "123!";

И вызвать скрипт без параметров, то в результате мы получим на экране текст:
123!
Usage:
  /home/warfair/Рабочий стол/script.p6 <arg1> <arg2>

Заметте, что при этом была вызвана функция say «123!», находящийся вне тела какой либо функции, и только после этого, произошла ошибка вызова MAIN.
Ссылку на функцию можно сохранить в переменную с помощью конструкции
sub MySub() {...};
my $var = &MySub;


Можно создавать анонимные функции и сохранять ссылки на них в скалярных переменных
my $r = sub ($a)
 {
     return $a*2;
 }
say $r(2);

В результате мы увидим 4
Tags:
Hubs:
Total votes 12: ↑12 and ↓0+12
Comments1

Articles