Последнее в категории Язык

Часть I
История и статистика

Perl 5.10 увидел свет в 20 день рождения языка — 18 декабря 2007 года. Уже прошло более двух лет, и за это время успели появиться девелоперские версии 5.11.0, 5.11.1, 5.11.2, 5.11.3 и 5.11.4, и вот-вот появится версия 5.12, предназначенная для использования в реальных приложениях.

Perl 5.10 представил много нововведений, и сегодня интересно посмотреть, как часто они используются авторами модулей CPAN — модулей, появившихся после релиза 5.10, либо обновленных с того времени.

На CPAN сейчас хранится около 80 000 модулей в 20 000 дистрибутивах, список авторов содержит около 8000 имен. Как часто здесь используются фичи Perl 5.10?

Ответ: новые фичи встречаются в двух сотнях модулей, созданных сотней авторов.


Часть II
Фичи Perl 5.10

Кратко о том, что появилось в Perl 5.10.

— Встроенная функция say, которая работает аналогично print, но добавляет перевод строки.

— Оператор сопоставления (смартматчинга) ~~ сопоставляет свои аргументы согласно здравому смыслу (и, разумеется, четким правилам, описанным в документации). Например, в этих примерах аргументы имеют разный тип, но используется один и тот же оператор.

$a ~~ /\d/

$a ~~ @list

@list ~~ %hash

— Составной оператор выбора под условным названием switch. С помощью новых ключевых слов given, when и default возможно создать условную конструкцию, аналогичную switch/case в C и других языках. Важное отличие в том, что внутри given происходит не простое сравнение, а сопоставление (или смартматчинг).

given($x) {
    when(/a/) {...}
    when('b') {...}
    default   {...}
}

— Модификатор state позволяет создавать лексические переменные, сохраняющие значение между вызовами подпрограммы. Использование state похоже на объявление автоматической переменной со словом static в C.

sub counter {
    state $c = 0;
    return ++$c;
}

— Новшества в регулярных выражениях. Регулярные выражения существенно переработаны, в частности, добавлены именованные сохраняющие скобки. В этой статье про регулярные выражение почти не упоминается, поскольку они достойны отдельного рассказа.

(?<name>)
\K
\R
%+
%-
\g<name>

— Бинарный оператор defined-or (//). Возвращает первый из аргументов, который содержит определенное (не undef) значение. Может использоваться и в варианте с присвоением.

Следующие два примера иллюстрируют логику, которая часто прослеживается в сообщениях о вакансиях.

$city = $arg // 'Moscow';

$vacancy{city} //= 'Moscow';


Продолжение будет.

Из 49 ответов на вопрос «@var — это массив или список?», оставшихся после отсеивания накруток сторонников массивов, сложилась такая картина общественного мнения:

Что для вас @var?

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

Как вы называете в повседневном обиходе переменную с именем @var? Массивом или списком?

Проголосуйте

Perl 5.10 в 2010-м

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

Моя презентация на «Перлбурге».

Презентация в пяти частях, основное содержание — о том, как и зачем используют возможности 5.10 в новых модулях на CPAN и мои примеры вариантов применения, которые я показывал на onperl.ru.


View more presentations from andy.sh.

use everywhere

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

Те, кто активно пользуются версией Perl 5.10, каждый раз пишут в начале файла инструкцию use v5.10 (в разных вариантах) или use Modern::Perl.

Брок Вилкокс создал (еще в августе 2009-го) модуль-прагму everywhere, и в документации прямо пишет о том, что сделал это для того, чтобы не писать надоедливые use 5.010.

Если вставить инструкцию everywhere до подключения других модулей, то ее аргумент автоматически превращается в соответсвующий вызов use внутри подключенных файлов.

use everywhere q(feature ':5.10');
use MyModule;

MyModule->my_sub($$);

Соответственно, внутри MyModule.pm теперь возможно использовать фичи 5.10:

package MyModule;

sub my_sub {
    say $_[1];
}

1;

Помимо 5.10 удается подключать и любые другие модули и прагмы. В документации, к примеру, упомянут вариант

use everywhere 'MooseX::Declare';

При попытке написать

use everywhere 'v5.10';

или

use everywhere '5.10.1';

появляется предупреждение о том, что v-string in use/require non-portable. Это удается обойти, написав переносимую (хотя и менее понятную человеку) конструкцию

use everywhere '5.010';

В качестве шутки можно избавиться от предупреждения и таким образом:

use v5.10;
use everywhere 'v5.10';

for и when

| Нет комментариев

То, что описано в этой заметке, вполне можно было бы записать в список каверзных задач на собеседовании.

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

use v5.10;

my @array = (1..20);
my $count = 0;
for(@array) {
    when(/[02468]$/) {$count++}
    say $_; # либо просто say;
}

say $count;

Вопрос: что будет напечатано на экране?

С последней строкой все понятно — она напечатает счетчик $count, и в нем содержится правильный ответ 10. Но вот say $_ внутри цикла напечатает лишь все нечетные числа от 1 по 19.

Блок кода, выполняемый функцией when(), содержит неявный оператор next, который не дает возможности продолжить выполнять тело цикла после первого удачного сопоставления. (Об этом сказано в документации.)

Продолжить цикл возможно стандартным образом, дописав continue:

for(@array) {
    when(/[02468]$/) {$count++; continue;}
    say $_;
}

В качестве дополнительного задания можно спросить, а что изменится, если в условии вместо регулярного выражения записать when($_ % 2).

А затем так: when(!($_ % 2)).

state (2)

| Нет комментариев

Хотя вчера я и написал, что ключевое слово state в перле похоже на static в C++, документация утверждает, что это не вполне так. Описано, впрочем довольно размыто.

Что еще нужно знать про state, кроме того, что эта инструкция стала доступна только с версии Perl 5.10?

Во-первых, state можно эмулировать и в ранних версиях.

{
    my $counter;
    sub counter {
        return ++$counter;
    }
}

print counter(), "\n"; # 1
print counter(), "\n"; # 2

Переменная $counter, оказываясь в замыкании, с одной стороны, недоступна для внешнего кода, а с другой, сохраняет свое значение между вызовами функции counter().

Во-вторых, для переменной, объявленной с ключевым словом state, возможно возвращать обычную ссылку, что дает возможность изменять значение переменной.

use v5.10;

sub counter {
    state $counter;
    ++$counter;
    return \$counter;
}

my $c = counter();
say ++$$c;        # 2
say ${counter()}; # 3

В-третьих, state-переменную допустимо инициализировать при создании, но это разрешено только для скаляров.

use v5.10;

sub counter {
    state $counter = 10;
    return ++$counter;
}

say counter(); # 11
say counter(); # 12

Попытка же инициализации списка или хеша приводит к ошибке:

state @a = (1, 2, 3);
Initialization of state variables in list context currently forbidden

state @a //= (1, 2, 3);
Can't modify private array in defined or assignment (//=)

В документации (perlsub) явно указано, что такие присвоения в языке не определены.

Тем не менее, при необходимости обойти это ограничение довольно просто.

state @a;
@a = (1, 2, 3) unless defined @a;

Why Perl?

| Нет комментариев

На этой неделе в рассылке Moscow.pm я задал простой вопрос: как показать начинающим программистам сильные стороны Perl?

В итоге получилось большое обсуждение на листе, где в том числе вспомнили картинку про создание мира, кросспостинг (позже удаленный) на ru_perl с руганью в комментариях в частности о том, надо ли лукавить перед студентами, сгущая краски, пост на ru_perl о том, что студентам надо преподавать не Perl, а Java и XML и перепост перепоста с интересным обсуждением в комментариях о нишах языков.

Stay tuned, епта.

Cравнить два списка — задача, которую без привлечения модулей (например, List::Compare) в перле решать не очень удобно.

Начинающих может удивить, что выражение @a == @b сравнивает не сами списки, а их размер.

С приходом Perl 5.10 возникает соблазн использовать для сравнения двух списков оператор смарт-матчинга (~~):

say @a ~~ @b;

Это хорошо работает до тех пор, пока в списках содержатся скаляры, например:

my @a = (1, 3, 5);
my @b = (1, 3, 5);
say @a ~~ @b; # 1

Однако следует помнить, что (по крайней мере, начиная с версии 5.10.1), операция сопоставления списков последовательно сопоставляет соответствующие элементы списков, используя тот же оператор ~~.

Поэтому следующий пример тоже напечатает единицу, хотя исходные списки — разные:

my @a = (1, 3, 5);
my @b = (1, qr/\d/, 5);
say @a ~~ @b; # 1

Chained defined-or

| Нет комментариев

До сегодняшнего дня я не задумывался о том, что действия с оператором defined-or (//) возможно объединять в цепочки, и это весьма удобно.

Например:

my $ip =
    $ENV{X_HTTP_FORWARDED_FOR} //
    $ENV{HTTP_X_REAL_IP}       //
    $ENV{REMOTE_ADDR};

Соответственно, добавить новый вариант и одновременно установить нужный приоритет значению, очень просто.

my $ip = 
    $page->param('request_ip') //
    $ENV{X_HTTP_FORWARDED_FOR} //
    $ENV{HTTP_X_REAL_IP}       //
    $ENV{REMOTE_ADDR};

Страницы

  • img

Об архиве

Эта страница содержит последние записи категории Язык.

Предыдущая категория — Тесты.

Следующая категория — Golf.

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