понедельник, 30 ноября 2009 г.

do, eval и return

Написал

my (@foo) = do {
...
return ...
};

держа в голове

my (@foo) = eval {
...
return ...
};

А не надо было в варианте с do использовать return, так как это выход не из do, а из подпрограммы, содержащей do.

:-)

вторник, 24 ноября 2009 г.

Parrot и Rakudo - перезагрузка

Как говорилось в "Parrot: PIR, PASM и L1", разработчики Parrot вынуждены переписать всю низкоуровневую часть проекта, неизменным останется лишь PIR и PGE.

Но, как показали разработчики Rakudo в Hague grant work: the new regex engine and NQP, PGE не слишком удобен на практике. Они собираются отказаться от него в пользу NQP-rx. Соответственно, PIR ждет та же учесть, которая постигла PASM с появлением первого.

Таким образом, по моему вменению, приобретя колоссальный опыт, разработчики Parrot и Rakudo вернулись почти к той же точке, с которой начинали.
Но не все так печально. Главное есть люди, есть идеи, есть решимость.

Да наступить "Рождество" в Perl мире!

понедельник, 16 ноября 2009 г.

Weighted Random

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

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

sub wrand($) {
my $data = shift;

my $total = 0;
$total += $_ foreach values %$data;

my @dist = ();
while (my ($value, $weight) = each %$data) {
push @dist, [$value, $weight / $total];
}

return sub {
my $rand = rand;
foreach (@dist) {
return $$_[0] if ($rand -= $$_[1]) < 0;
}
return $dist[-1][0];
}
}

Пример использования:

my %foo = (
# value => weight
"one" => 3,
"two" => 2,
"three" => 1,
);

my $wrand = wrand(\%foo);
print $wrand->(), "\n" for 1 .. 10;

Если веса являются целыми числами, то можно использовать более быструю версию:

sub iwrand($) {
my $data = shift;
my %dist = ();
while (my ($value, $weight) = each %$data) {
$dist{keys %dist} = $value foreach 1 .. $weight;
}
return sub {
$dist{int rand keys %dist};
};
}

Смотрите также модуль Math::Random - Random Number Generators.

понедельник, 9 ноября 2009 г.

Светлая и темная стороны силы Perl

"Существует множество способов сделать это", и в каждой конкретной ситуации следует предпочесть наиболее простой, ясный и оптимальный вариант. Вот это белая сторона силы Perl.

На темной же стороне те "Just another Perl Hackers", кто, используя мощь Perl, делает простые вещи сложными в угоду своему самолюбию.

понедельник, 2 ноября 2009 г.

"Сегодня без..." - точка, превратившаяся в запятую

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

sub sum(&$@);
sub sum(&$@) {
my $sub = shift;
my ($sum, $h, @t) = @_;
if (defined $h) {
sum { $sub->(@_) } $sum + $h, @t;
} else {
$sub->($sum);
}
}

my @vector = 1 .. 5;
sum { print shift } 0, @vector;

Вот только эта точка, поставленная в конце цикла заметок "Сегодня без...", превратилась в запятую!