Pull to refresh

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

Reading time 4 min
Views 6.3K
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();
Tags:
Hubs:
+13
Comments 8
Comments Comments 8

Articles