1. Особенности работы с переменными и литералами в Perl6
В предыдущей статье я описывал особенности работы с переменными, а также затронул контексты. В данной статье, я хочу поделиться результатми своих экспериментов и поисков на тему использования переменных, а также коротко описать особенности анонимных блоков кода.
Приступим
В Perl6 имеется возможность указать тип переменной при объявлении.
Например:
При таком объявлении переменной $var можно будет присвоить только число. В случае если переменной попытаться присвоить строку, либо другой тип, то никаких автоматических приведений типов выполняться не будет — работа скрипта будет остановлена с ошибкой о проверке типов. В качестве типа может быть указан любой существующий тип данных, даже пользовательские классы.
Конвертировать из указанного типа в другие можно без каких либо особенных ограничений.
При таком объявлении переменной, её изначальное значение будет Int(), и использовать данное значение нельзя — происходит это из-за того, что автоматического вызова конструктора не происходит, и переменная получает неопределенное значение указанного типа. Для создания нового экземпляра объекта при объявлении переменной можно использовать конструкцию
Узнать, имеет ли переменная какое либо значение можно с помощью метода defined:
Ещё один способ указания типа это конструкция
Однако в последней, на данный момент (12.09), версии Rakudo-star данный способ ещё не работает.
Возможен так же следующий способо указания типа:
однако в (12.09) так же не работает, поэтому не могу сказать что либо о особенностях данного способа.
Перейдем к основным операциям — естесственно список этот не полный, но Я приведу список основных операций, которыми мы будем пользоваться:
Теперь о блоках:
Блоки в Perl 6 могут использоваться как данные: отдельные блоки можно присваивать скалярным переменным и после исполнять их:
При вызове блока на исполнение результатом вызова становится последнее вычисленное значение в этом блоке. В данном примере вычисленным значением является константа 1. Внутри блоков оператор return для окончания работы блока использовать нельзя: он будет завершать выполнение функции, в которой вызывается блок.
Блоки можно использовать как аргументы при вызовах функций:
Внутри блоков можно объявлять переменные, или переопределять существующие: блок задает свою область видимости переменных, и изменения переменных объявленных внутри блока не влияют на одноименные переменные вне этого блока.
В следующем коде
будет выведена строка 'Начальное значение переменной', т.к. при создании переменной $closure использовалась переменная объявленная в глобальной области видимости, и даже после определения внутри блока переменной с таким же названием $a, будет использоваться первая.
В следующем коде будет использоваться локальная для блока переменная $a, даже при условии, что её обласить видимости уже не доступна из места вызова.
В предыдущей статье я описывал особенности работы с переменными, а также затронул контексты. В данной статье, я хочу поделиться результатми своих экспериментов и поисков на тему использования переменных, а также коротко описать особенности анонимных блоков кода.
Приступим
В 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;
- any (
Теперь о блоках:
Блоки в 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();