Perl6 — Операции над переменными, анонимные блоки

    1. Особенности работы с переменными и литералами в Perl6
    В предыдущей статье я описывал особенности работы с переменными, а также затронул контексты. В данной статье, я хочу поделиться результатми своих экспериментов и поисков на тему использования переменных, а также коротко описать особенности анонимных блоков кода.
    Приступим


    В Perl6 имеется возможность указать тип переменной при объявлении.
    Например:
    my Int $var;

    При таком объявлении переменной $var можно будет присвоить только число. В случае если переменной попытаться присвоить строку, либо другой тип, то никаких автоматических приведений типов выполняться не будет — работа скрипта будет остановлена с ошибкой о проверке типов. В качестве типа может быть указан любой существующий тип данных, даже пользовательские классы.
    Конвертировать из указанного типа в другие можно без каких либо особенных ограничений.
    При таком объявлении переменной, её изначальное значение будет Int(), и использовать данное значение нельзя — происходит это из-за того, что автоматического вызова конструктора не происходит, и переменная получает неопределенное значение указанного типа. Для создания нового экземпляра объекта при объявлении переменной можно использовать конструкцию
    my SomeClass $x .= new(a,r,g,s);
    my $x = SomeClass.new(a,r,g,s);
    

    Узнать, имеет ли переменная какое либо значение можно с помощью метода defined:
    my Int $x;
    say $x.defined;   #False
    


    Ещё один способ указания типа это конструкция
    my $x is Int;

    Однако в последней, на данный момент (12.09), версии Rakudo-star данный способ ещё не работает.
    Возможен так же следующий способо указания типа:
    my Array of Array of Int @x;
    

    однако в (12.09) так же не работает, поэтому не могу сказать что либо о особенностях данного способа.

    Перейдем к основным операциям — естесственно список этот не полный, но Я приведу список основных операций, которыми мы будем пользоваться:
    • Операции с числами:
      • Типичные бинарные и унарные операции
        Это операции +, -, *, /
        В дополнении к вышеперечисленным можно использовать операции взятия остатка от деления (%, mod), возведения в степень (**), инкремент и декремент (++, --), взятие целой части от деления (div)
      • Побитовые операции: Побитовое «И» (+&), побитовое «ИЛИ» (+|), побитовый сдвиг (+<, +>), побитовое «XOR» (+^)
      • Операции сравнения: ==, !=, <, >, >=, <=.

    • Операции со строками:
      Склеивание двух строк
      ('a'~'b')

      Повторение строки n раз
      ('a' x 10)

      Сравнение строк: Строки равны (eq), неравны (ne), по алфавиту строка 1 идет раньше строки 2 (lt, before), позже (gt, after), раньше или совпадают (le), позже или сопадают (gt)
    • -Операции с логическим типом:
      И (?&), ИЛИ (?|), XOR (?^), NOT (!)
    • -Использование Junction()
      Junction это специальный тип, для группового сравнения — если написать
      $a == any(1, 2, 3)

      то условие будет выполнено, если переменная $a равна хотябы одному из перечисленных значений.
      Возможные операторы
      • any ($a==1 or $a==2 or $a==3)
      • all ($a==1 and $a==2 and $a==3)
      • one (Переменная $a равна только одному из указанных значений),
      • none ($a!=1 and $a!=2 and $a!=3)

      -Определение максимального (max) или минимального (min) числа
      $a = 10 min 4;
      $b = 20 max 99;

      При использовании строк в качестве операндов сравнение идет по алфавитному порядку.

      -Тернарный оператор
      $ifValue ?? "yes" !! "no"

      Первый операнд преобразуется к булиновскому типу и если его значение истина то возвращается второй операнд, иначе третий.

      -Использование метаоператора
      Имеется возможность применения определенной операции для каждого элемента массива:
      @a = (1, 2, 3);
      @b = @a X* 2;   #Умножение каждого элемента массива на 2, и создание нового массива
      @c = @a X** 2;  #Возведение в квадрат каждого элемента массива и занесение результата в новый массив


      -Перебор всех элементов
      Для того чтобы выполнить операцию для всех элементов массива используется конструкция >>operator>>
      @a = 1, 2, 3;
      @b = @a>>**>>2, 100, 500;

      В данном выражении все элементы массива @a возводятся в квадрат, создавая новый массив, к полученному массиву добавляются два числа: 100 и 500
      В результате в массиве @b содержится (1, 4, 9, 100, 500)

      -Оператор zip
      используется для попарного выделения элементов из двух массивов:
      @a = (1, 2, 3);
      @b = (4, 5, 6);
      @c = @a Z @b;   #(1, 4, 2, 5, 3, 6)


      Сокращенная форма записи оператора
      Для того чтобы сложить все числа можно воспользоваться записью [+]
      @a = 1, 2, 3;
      $a = [+] @a;

      В результате получается $a = 1+2+3;

      Создание псевдонима
      Для переменной можно создать псевдоним, который будет считаться вторым именем переменной. Переменные указывают на одну и туже область в памяти, поэтому изменения через одно имя переменной будут видны и через второе имя переменной. Создание псевдонима обозначается как ':='
      $a = 1;
      $b := $a;


      Создание неизменяемой переменной
      Для создания неизменяемой переменной используется оператор '::=' например
      my $a ::= "aaa";
      

      Однако в текущей версии (12.09) такое объявление выдает ошибку компиляции

      Получение ссылки на переменную
      Можно получать ссылку на переменную с помощью '\':
      $a = 10;
      $b = \$a;




    Теперь о блоках:
    Блоки в Perl 6 могут использоваться как данные: отдельные блоки можно присваивать скалярным переменным и после исполнять их:
    $b = 10;
    $a = { $b = 1; };
    $a();
    say $b;   # $b=1;

    При вызове блока на исполнение результатом вызова становится последнее вычисленное значение в этом блоке. В данном примере вычисленным значением является константа 1. Внутри блоков оператор return для окончания работы блока использовать нельзя: он будет завершать выполнение функции, в которой вызывается блок.
    Блоки можно использовать как аргументы при вызовах функций:
    func($arg1, $arg2, { say 'this is a block'; });

    Внутри блоков можно объявлять переменные, или переопределять существующие: блок задает свою область видимости переменных, и изменения переменных объявленных внутри блока не влияют на одноименные переменные вне этого блока.
    В следующем коде
    my $a = 'Начальное значение переменной';
    my $closure = { say $a; };
    {
        my $a = 'Измененное значение переменной';
        $closure();
    }

    будет выведена строка 'Начальное значение переменной', т.к. при создании переменной $closure использовалась переменная объявленная в глобальной области видимости, и даже после определения внутри блока переменной с таким же названием $a, будет использоваться первая.
    В следующем коде будет использоваться локальная для блока переменная $a, даже при условии, что её обласить видимости уже не доступна из места вызова.
    my $a = 'Начальное значение переменной';
    my $closure;
    {
        my $a = 'Измененное значение переменной';
        $closure = { say $a; };
    }
    $closure();
    • +13
    • 5,7k
    • 8
    Поделиться публикацией
    Комментарии 8
      –1
      Перловая каша с граблями, как всегда :)
        +4
        А где тут каша и/или грабли, уточните, пожалуйста, очень интересно посмотреть.
        0
        Про блоки, начиная со слов
        Теперь о блоках. Блоки в Perl 6 могут...
        — да как бы так всегда было
          0
          Заметте, что я не писал фразы наподобии «в отлии от Perl5», я лишь описывал что можно делать с блоками в Perl6.
          +1
          Здорово! Я бы только еще упомянул оператор ::=, позволяющий создавать неизменяемые переменные.
            0
            Если я правильно понял описание, то этот оператор должен создать псевдоним для переменной указанной справа и сделать чтобы через переменную слева нельзя было изменять ту что справа, но в версии 12.09 этого не происходит: там переменная слева не только остается изменяемой, но и не делается ссылкой, поэтому я не мог сказать что либо про этого оператора. Возможно просто в этой версии ещё нет правильного поведения, но возможно и я не прав, поэтому я могу добавить оператора в статью, если вы подтвердите что я был прав.
              0
              Например

              my $x ::= "aaa"; $x ~= "bbb";

              Конкатенация не проходит.
                0
                Спасибо. Добавил в статью сразу после создания псевдонима.

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое