Архив Июнь 2010

Для этого фокуса потребуется взять один Class::Accessor и один Test::Deep, замешав их в одном модуле:

package MyTest;

use base 'Class::Accessor';
use Test::Deep;

__PACKAGE__->mk_accessors qw(mytest);

1;

Модуль Class::Accessor создаст в пакете MyTest метод mytest(), который должен работать как пара сеттер — геттер для установки поля mytest (точнее, $self->{mytest}). Тестируем:

use v5.12;
use MyTest;

my $test = new MyTest;
$test->mytest('test');
say "mytest=", $test->mytest;

И видим, что никакое значение mytest=test не устанавливается. Комментируем в файле MyTest.pm строку, подключающую модуль Test::Deep, и все работает:

mytest=test

Раскомментируем обратно и попробуем немного по-другому:

$test->set('key', 'value');
set $test('key', 'value');

Опять не работает. Но по-другому мы пробуем уже после того, как заглянули в исходник Test::Deep и увидели там безусловный экспорт функции set:

@EXPORT = qw( eq_deeply cmp_deeply cmp_set cmp_bag cmp_methods
    useclass noclass set bag subbagof superbagof subsetof
    supersetof superhashof subhashof
);

В свою очередь, внутри методов-аккессоров, которые создает Class::Accessor, используются вызовы $self->set(...), которые в модуле, унаследованном от него, попадают напрямую в Test::Deep::set().

Неуклюжее быстрое решение: подсказать компилятору, куда направлять внутренние вызовы методов set:

package MyTest;

use base 'Class::Accessor';
use Test::Deep;

*set = *Class::Accessor::set;

__PACKAGE__->mk_accessors qw(mytest);

1;

RPC::XML v. XXX

| 1 комментарий

Из записок на языке Эразма Роттердамского.

Сделали sandbox на новеньком сервере, стали запускать тесты — половина не работает. Вместо ok видим wanted a data type, got `i8'. Кто говорит? Слон? Ошибку можно разглядеть в XML, который как-то где-то формируется через третьи руки. Разумеется, автор кода на этой неделе в отпуску, поэтому тратим еще час на то, чтобы выяснить, что сообщение об ошибке формирует модуль RPC::XML.

Мы-то уже догадались, что i8 — скорее всего тип целочисленных данных, потому что в стандарте есть тип i4, но про i8 там ни слова.

Еще какое-то время, и выясняется, что на другом сервере такой ошибки нет. Остается догадаться посмотреть $RPC::XML::VERSION. Ну точно, в одном месте — 1.36, в другом — 1.41.

Читаем документацию и удивляемся: тип i8 добавлен как нестандартный. Потому что им уже кто-то пользуется. Смотрим на спан и удивляемся еще раз: последняя версия там — 0.70. Ij? (в русской раcкладке — шо?) Может github? Там тоже 0.70. Начинаем подозревать всех в том, что они втихаря переписывают модуль прямо на серверах. Но в итоге смотрим в исходник версии 0.70 и видим, что версия модуля — 1.50. Релаксируем.

Бельгийский Perl-воркшоп (который в этом году удобно проходит в столичном Брюсселе) расположился в помещении The Hub Brussels, которое раньше было цехом шоколадной фабрики.

В первой части были приведены три программы, работающие под Perl 5.12, и предлагалось определить, что они выведут.

А выведут они следующее.

Программа А.

use v5.12;
my @letters = 'a'..'z';
for (my ($number, $char) = each @letters) {
    say "$number $char";
}

0 a
0 a

Программа Б.

use v5.12;
my @letters = 'a'..'z';
say $_ for each @letters;

0
a

Программа В.

use v5.12;
my @letters = 'a'..'z';
say $_ foreach @letters;

a
b
c
. . .
x
y
z

На сайте конференции YAPC::Europe открыт список одобренных заявок на доклады.

Из новшеств бросается в глаза, например, три сессии блиц-докладов — по одной на каждый день. Разумеется, будут доклады про Perl 5.12 и Perl 6. И остальное — на любой вкус, от введения в Git и Perl-сообщество до работы с базами данных и XS. Join and Enjoy!

Участники собрались по интересам.

Наим Шафиев. AnyEvent::HTTPBenchmark.


Руслан Закиров. TODO по Devel::PPAP.


Алексей Капранов. Job-сайт.

Джонатан Вортингтон. Rakudo.


Анатолий Шарифулин. Mojolicious cookbook.


Про XXX

| Комментариев: 2

На спане есть модуль Инги дёт Нета (Брайана Ингерсона) под названием XXX, предназначенный для — ха! — для отладки.

Модуль экспортирует несколько функций WWW, XXX, YYY и ZZZ, которые печатают дамп того, что находится справа. То есть достаточно вписать в нужное место XXX, и выполнение программы прекратится отладочным сообщением:

use v5.12;
use XXX;

XXX my @digits = 'a'..'f';

--- a
--- b
--- c
--- d
--- e
--- f
...
  at 1.pl line 4

По умолчанию дамп делается в формате YAML, но это возможно переопределить, например:

use v5.12;
use XXX -with => 'Data::Dumper';

XXX my $person = {sex => 'male', age => 30};

$VAR1 = {
  'age' => 30,
  'sex' => 'male'
};

  at 2.pl line 4

Вызов XXX приводит к завершению программы (die), а WWW печатает предупреждение (warn).

Несмотря на то, что все равно приходится явно подключать модуль (use XXX), подход очень интересный: написать в начале (или любой другой части — функция возвращает все свои аргументы) строки три буквы (хотя еще удобнее было бы, если бы названия функция были в нижнем регистре) намного проще и быстрее, чем, например, say Data::Dumper($var).

Йозеф Кутей обновил дистрибутив Universe::Galaxy, который содержит модуль с бесконечным названием Universe::ObservableUniverse::Filament::SuperCluster::Cluster:: Group::Galaxy::Arm::Bubble::InterstellarCloud::SolarSystem::Earth.

Из двух доступных методов нам важен ultimate_answer, который дает ответ на главный вопрос жизни, вселенной и всего такого.

use v5.10;

Universe::ObservableUniverse::Filament::SuperCluster::⏎
Cluster::Group::Galaxy::Arm::Bubble::InterstellarCloud::⏎
SolarSystem::Earth;

say Universe::ObservableUniverse::Filament::SuperCluster::⏎
Cluster::Group::Galaxy::Arm::Bubble::InterstellarCloud::⏎
SolarSystem::Earth->ultimate_answer;

42

А еще на спане есть модуль Acme::Test::42, который работает аналогично любому другому современному модулю, основанном на Test::Builder, но проверяет, вычислен ли ответ на главный вопрос.

Соответственно, тестируем:

use Universe::ObservableUniverse::Filament::SuperCluster::⏎
Cluster::Group::Galaxy::Arm::Bubble::InterstellarCloud::⏎
SolarSystem::Earth;

use Acme::Test::42 qw(no_plan);

ok(Universe::ObservableUniverse::Filament::SuperCluster::⏎
Cluster::Group::Galaxy::Arm::Bubble::InterstellarCloud::⏎
SolarSystem::Earth->ultimate_answer);

ok 1
1..1

 

Серия вопросов для собеседования на понимание работы each из Perl 5.12 в применении к массивам (требовать заранее знать, что делает each @a, разумеется не обязательно, можно и объяснить, но вопросы остаются теми же).

Программа А.

use v5.12;
my @letters = 'a'..'z';
for (my ($number, $char) = each @letters) {
    say "$number $char";
}

Программа Б.

use v5.12;
my @letters = 'a'..'z';
say $_ for each @letters;

Программа В.

use v5.12;
my @letters = 'a'..'z';
say $_ foreach @letters;

Что эти программы напечатают и почему?

Британец Барри Уолш пишет в своем блоге о важной особенности работы оператора each в Perl 5.12.

Вызов each, примененный к массиву, возвращает пару величин: индекс и значение очередного элемента. Очевидно, что в пределах цикла (напрмер, while) each сохраняет указатель на текущую позицию.

use v5.12;

my @letters = 'a'..'z';
while (my ($number, $char) = each @letters) {
    say "$number $char";
}

Однако, менее очевидно, что если преравать итерацию, то при следующем вызове нумерация будет продолжена с прежней позиции. Например:

use v5.12;

my @letters = 'a'..'z';
while (my ($number, $char) = each @letters) {
    say "$number $char";
    last if $number == 15;
}

say "Second loop";
while (my ($number, $char) = each @letters) {
    say "$number $char";
}

В этом примере напечатается следующее:

0 a
1 b
2 c
. . .
14 o
15 p
Second loop
16 q
17 r
. . .
24 y
25 z

Видно, что each продолжил с того же места, где остановился в первом цикле.

Сбросить счетчик удается вызовом keys @array или values @array. Также важно, что изменение массива (с помощью push или pop) и даже присвоение новых значений не изменяет позицию счетчика:

use v5.12;

my @letters = 'a'..'z';
while (my ($number, $char) = each @letters) {
    say "$number $char";
    last if $number == 15;
}

@letters = 'A'..'Z';
say "Second loop";
while (my ($number, $char) = each @letters) {
    say "$number $char";
}

В этом случае второй цикл упрямо продолжит с того же места, но уже с другим содержанием:

0 a
1 b
2 c
. . .
14 o
15 p
Second loop
16 Q
17 R
. . .
24 Y
25 Z

Запоздавшая пятничная иллюстрация о том, как правильно писать слово япси в зависимости от места проведения конференции.

YAPC

Во-первых, у нас теперь два спонсора: REG.RU и uCoz.

Во-вторых, стоимость прогулки на теплоходе 14 июня уменьшилась на 60%. Все на борт!

Про /m

| 1 комментарий

Бывает, что какой-то возможностью либо настолько редко пользуешься, либо она настолько неудобна, что про нее забываешь напрочь.

Сегодня меня заново познакомили (hsw++) с модификатором регулярных выражений /m.

В дизайне регулярных выражений Perl 5 есть аж пять метасимволов, совпадающие с границами строк (физических или логических):

^ $ \A \Z \z

И на все это наслаивается модификатор /m, изменяющий действие первых двух из списка. И, до кучи, пара символов для переноса строк (\n и \R). Полное безобразие. Иными словами, отказ от /m в Perl 6 — очень правильное решение.

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

Страницы

  • img

Об архиве

Страница содержит архив записей за Июнь 2010, расположенных по убыванию.

Май 2010 — предыдущий архив.

Июль 2010 — следующий архив.

Смотрите новые записи на главной странице или загляните в архив, где есть ссылки на все сообщения.