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

    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
    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 1

      +1
      Можно еще так например: sub f () returns Int { return 1; }
      или короче: sub f () of Int { return 1; }

      конструкция

      my Int sub func($a)

      работает только в сочетании с my.

      «Параметрам функции можно дополнительно указывать, можно ли изменять эти параметры внутри функции»

      Следует отметить, что по-умолчанию все параметры функций в Perl 6 неизменяемы. Например sub f ($a) { $a += 1;} my $b = 2; f($b); бросает исключение «Cannot assign to a readonly variable or a value». Запись is rw меняет это поведение. Еще можно написать is copy, тогда внутри f можно будет изменять $a, но на $b это никак не повлияет.

      Only users with full accounts can post comments. Log in, please.