среда, 30 декабря 2015 г.

Сильные и слабые ссылки в Perl

Сильные ссылки

use strict;
use warnings;
use Scalar::Util qw/weaken/;
$\ = "\n";

my $ref; # Ссылка на какую-либо сущность
{
    my $a = 3;
    $ref = \$a;  # Берём ссылку на переменную $a.
                 # $ref - в данном случае является сильной ссылкой.

    # Так как область жизни переменной $a ограничена данным блоком,
    # то по выходу из него переменная $a должна быть уничтожена,
    # но так как количество ссылок, ссылающихся на неё не равно нулю,
    # то этого не происходит.
}

print $$ref; # 3
undef $ref;  # Обнуляем значение сильной ссылки, после чего
             # счетчик ссылок на переменную $a уменьшается на единицу 
             # и теперь он равняется нулю, а переменная $a завершает 
             # своё существование.

вторник, 29 декабря 2015 г.

Perl изнутри: файл INTERN.h

Продолжаем изучать файлы исходников и на этот раз рассмотрим файл "INTERN.h". Вот его содержимое:

воскресенье, 27 декабря 2015 г.

Шифрование текста с помощью операции XOR

Вспомним таблицу истинности для данной операции:
x y out
0 0 0
0 1 1
1 0 1
1 1 0

Т.е. если количество единиц нечётно, то получаем истину, в противном
случае ложь. Используя данный факт, можно восстановить исходное сообщение.
Допустим выше x - это текст, y - это ключ, out - зашифрованное сообщение.
Таким образом, если применить к out повторную операцию с ключом y, то
можно получить исходный x.
y out x 
0 0   0 
1 1   0 
0 1   1 
1 0   1 

Теперь рабочая реализация данного принципа.

воскресенье, 20 декабря 2015 г.

Обратный отсчёт c Curses

Используя возможности библиотеки curses, реализуем обратный отсчет от 9 до 0 в виде электронного циферблата.


Для нашей затеи потребуется одноимённый модуль-обёртка для Perl - Curses.

воскресенье, 13 декабря 2015 г.

Perl изнутри: файл EXTERN.h

Получаем исходники

 

Идём в perlgit, находим способ для получения репозитария исходников perl:
% git clone git://perl5.git.perl.org/perl.git perl 

Любуемся и приступаем к изучению, а заодно вспомним C. Начнём с файла заголовков "EXTERN.h". Вот его основное содержимое:

четверг, 10 декабря 2015 г.

Настраиваем порядок определения методов при множественном наследовании в Perl

Как это работает по умолчанию?

package Top;

sub new { bless {}, shift } 

sub name { __PACKAGE__ }

package Left;
use base 'Top';

package Right;
use base 'Top';

sub name { __PACKAGE__ }

package Bottom;
use base qw/Left Right/;

package main;

my $obj = Bottom->new;
print $obj->name;

вторник, 8 декабря 2015 г.

Реализуем отложенные функции с помощью автозагрузчика AutoLoader

Ситуация: есть большая библиотека с несколькими десятками функций, причем
львиная доля из них нам не потребуется, а только лишь несколько из них будут
востребованы, да и то не факт. В данном случае, чтобы не перетруждать перл
анализом "ненужных" функций, есть возможность отложить это занятие до того
момента, когда в какой-либо конкретной функции из библиотеки появится надобность.

Один из способов для достижения подобной задачи заключается в использовании
автозагрузчика функций - модуля AutoLoader и его помощника - модуля AutoSplit.

суббота, 5 декабря 2015 г.

"Постоянные" переменные, state и замыкания

use strict;
use warnings;
use utf8;
use v5.14;

# Вариант 1.
# Постоянная лексическая переменная, объявленная
# с помощью state - недоступна для внешнего кода.
sub обновить { state $переменная += shift || 10 }
say обновить($_) for 0..4;
say '-' x 50;

# Вариант 2.
# В отличие от первого варианта здесь, как и должно быть, 
# значение "my" переменной вычисляется без оглядки на её
# предыдущее состояние. 
sub обновить_снова { my $переменная += shift || 10; }
say обновить_снова($_) for 0..4;
say '-' x 50;

# Вариант 3.
# Достигаем аналогичного результата, как в варианте 1,
# используя замыкание.
sub обновить_ещё_разок { my $переменная; sub { $переменная += shift || 10 } } 
my $функция = обновить_ещё_разок;
say $функция->($_) for 0..4;
say '-' x 50;

# Вариант 4.
# Достигаем аналогичного результата, как в варианте 1,
# используя замыкание и постоянную лексическую переменную.
sub обновить_последний_раз { sub { state $переменная += shift || 10 } } 
my $новая_функция = обновить_последний_раз;
say $новая_функция->($_) for 0..4;

пятница, 4 декабря 2015 г.

Операции над множествами в perl

use strict;
use warnings;
no warnings 'experimental';
$\="\n";

# Наши подопытные множества, представленные в виде массивов.
my @A = (1,1,1,8,8,9,2);
my @B = (2,8,8,8,2,3);
my @C = (4,8,8,8,2,3);

my @D;

# 1. Объединение
@D = keys { map { $_ => undef } @A, @B, @C };
print "Объединение: @D";

# 2. Пересечение
@D = keys { map { $_ => undef } grep { $_ ~~ @B and $_ ~~ @C } @A };
print "Пересечение: @D";

# 3. Разность
@D = keys { map { $_ => undef } grep { not $_ ~~ @B and not $_ ~~ @C } @A };
print "Разность: @D";

воскресенье, 27 сентября 2015 г.

Делаем, как взрослые, указываем номер версии программы

В перл номер версии хранится в глобальной переменной $VERSION, доступ к которой можно получить явно $ModuleName::VERSION, либо используя стандартный для всех модулей метод: ModuleName->VERSION.

Есть несколько способов нумерации модулей. Рассмотрим, два наиболее распространённых способов это АА.АА и АА.АА.АА версии, где А - это любое число.

четверг, 24 сентября 2015 г.

Каталог SQL-запросов

Для случая, если в проекте используется много SQL-запросов, имеет смысл вынести их в отдельный модуль(и), в котором организовать их храненение в виде хеша, ключи которого будут указывать назначение конкретного запроса. Эдакая разновидность документации непосредственно с использованием кода. Само же хранение всех SQL-запросов в одном месте упрощает их использование.

Пример:

Упрощаем доступ к хешу по ключу, с использованием $; переменной

use strict;
use warnings;

$\="\n";

# Предположим, что имеется некоторый хеш, ключи которого выглядят так:

my %foo = (
    'Close|___|your|___|window' => 'Closed',
    'Open|___|the|___|door'     => 'Opened',
    'Just|___|three|___|words'  => 'Amazing' 
);

# т.е. в имени ключа используется разделитель '|___|'.
# И для того, чтобы не писать весь этот ужас каждый раз в имени ключа,
# перл предоставляет небольшое упрощение для данной задачи.
# К примеру, вместо вот этого:

print $foo{'Open|___|the|___|door'};
print $foo{'Just|___|three|___|words'};

print '-' x 15;
# можно написать вот так:

$; = '|___|'; # в данной ситуации эта волшебная переменная,
                  # позволяет настраивать разделитель
                  # для доступа к элементам хеша по ключу.
print $foo{'Open', 'the', 'door'};
print $foo{'Just', 'three', 'words'};

# но можно сделать еще более читабельным наименование ключа:
print $foo{qw/Close your window/};

# Итог, при любом способе, будет предсказуем:
#
# Opened
# Amazing
# ---------------
# Opened
# Amazing
# Closed

понедельник, 21 сентября 2015 г.

Пара слов об IPC

IPC:

    сигналы;
    очереди;
    каналы;
    безопасные подпроцессы;
    сокеты;
    семафоры.

Perl использует возможности юникс для реализации IPC: сигналы, именованные каналы, каналы, сокеты, SysV IPC вызовы.

Не так страшен goto, как его малюют

goto LABEL
goto EXPR
goto &NAME


goto LABEL - продолжить выполнение с LABEL. С помощью неё нельзя войти в подпрограмму, цикл и любую другую конструкцию, для которой необходимо задать начальные условия.

воскресенье, 20 сентября 2015 г.

Особенность использования warn, die с "\n"

perl v5.18.2

Поведение warn с использованием символа новой строки "\n":

test.pl
warn "Hello";
warn "World\n";
warn "Wor\nld";

perl test.pl
Hello at m.pl line 4.
World
Wor
ld at m.pl line 6.

Отладка, включаем и выключаем по желанию

"Наиболее эффективным инструментом отладки всё ещё 
остаётся внимательное размышление, связанное с 
благоразумно расположенными print выражениями."
Брайн Керниган "Unix для начинающих. 1979 г"

Такую возможность для управляемой отладки предоставляет глобальная переменная $DEBUG в модуле, который мы хотим отлаживать время от времени. Сами же отладочные вызовы должны срабатывать только при истинном значении $DEBUG. Включать и выключать отладочный режим можно простым переопределением значения переменной $DEBUG в программе, которая использует данный модуль.