Каковы некоторые элегантные функции или использование Perl? - PullRequest
35 голосов
/ 13 марта 2009

Что? Красивый Perl? Элегантный ? Должно быть, он шутит!

Это правда, там какой-то уродливый Perl. И под некоторыми я имею в виду много. Мы все это видели.

Ну да, это символ супа. Не так ли?

Да, есть символы. Также как у «математики» есть «символы». Просто мы, программисты, лучше знакомы со стандартными математическими символами. Мы выросли, чтобы принимать символы из наших родных языков, будь то ASM, C или Pascal. Perl просто решил иметь еще несколько.

Ну, я думаю, мы должны избавиться от всех ненужных символов. Делает код лучше.

Язык для этого уже существует. Это называется Lisp. (и скоро, perl 6 .)

Хорошо, умный парень. Правда, я уже могу изобретать свои собственные символы. Они называются функциями и методами. Кроме того, мы не хотим изобретать APL .

О, фальшивое альтер эго, ты такой смешной! Это правда, Perl может быть довольно красивым. Это может быть довольно некрасиво. С Perl, TIMTOWTDI .

Итак, какие ваши любимые элегантные фрагменты кода Perl?

Ответы [ 14 ]

28 голосов
/ 13 марта 2009

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

my $result = $obj->method(
    flux_capacitance       => 23,
    general_state          => 'confusion',
    attitude_flags         => ATTITUDE_PLEASANT | ATTITUDE_HELPFUL,
);
24 голосов
/ 16 марта 2009

Мои любимые части элегантного Perl-кода вовсе не обязательно элегантны. Они мета-элегант и позволяют вам избавиться от всех тех вредных привычек, в которые многие разработчики Perl проникли. Мне потребовались бы часы или дни, чтобы показать их все в деталях, которых они заслуживают, но в качестве краткого списка они включают:

  • autobox , который превращает примитивы Perl в первоклассные объекты.
  • autodie , который заставляет встроенные модули генерировать исключения при сбое (устраняя большинство потребностей для конструкции or die...). Смотрите также мой блог autodie и video ).
  • Moose , обеспечивающий элегантный, расширяемый и правильный способ написания классов на Perl.
  • MooseX :: Declare , что обеспечивает синтаксическую мощь при использовании Moose.
  • Perl :: Critic , ваш персональный, автоматический, расширяемый и осведомленный рецензент кода. Смотрите также этот Perl-tip .
  • Devel :: NYTProf , который предоставляет мне наиболее подробную и полезную информацию о профилировании, которую я видел на любом языке программирования. Смотрите также Блог Тима Бунса .
  • PAR , Perl Archiver, для объединения дистрибутивов и даже превращения целых программ в автономные исполняемые файлы. Смотрите также этот Perl-tip .
  • Perl 5.10, обеспечивающий потрясающие улучшения регулярных выражений , smart-match , оператор переключения , определено или, и переменные состояния .
  • Padre , единственный Perl-редактор, который объединяет лучшие биты из вышеперечисленного, является кроссплатформенным, полностью бесплатным и открытым исходным кодом.

Если вам лень переходить по ссылкам, я недавно сделал доклад на Linux.conf.au о большинстве вышеперечисленных. Если вы пропустили это, есть видео этого онлайн (ogg theora). Если вам лень смотреть видео, я сделаю значительно расширенную версию доклада в качестве учебного пособия для OSCON в этом году (под названием , что делает Perl правильным ).

Всего наилучшего,

Пол

19 голосов
/ 13 марта 2009

Я удивлен, что никто не упомянул преобразование Шварца.

my @sorted =
  map  { $_->[0] }
  sort { $a->[1] <=> $b->[1] }
  map  { [ $_, expensive_func($_) ] }
@elements;

А при отсутствии оператора slurp

my $file = do { local $/; readline $fh };
16 голосов
/ 13 марта 2009

Есть список файлов, которые пользователь хочет обработать вашей программой? Не хотите случайно обработать программу, папку или несуществующий файл? Попробуйте это:

@files = grep { -T } @files;

И, как по волшебству, вы отсеяли все неподходящие записи. Не хотите игнорировать их молча? Добавьте эту строку перед последней:

warn "Not a file: $_" foreach grep { !-T } @files;

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

my @good;
foreach(@files) {
  if(-T) {
    push @good, $_;
  } else {
    warn "Not a file: $_";
  }
}

grepmap) можно использовать для сокращения кода при сохранении его высокой читаемости.

11 голосов
/ 16 марта 2009

Конструкция "или умри":

open my $fh, "<", $filename
    or die "could not open $filename: $!";

Использование qr // для создания грамматик:

#!/usr/local/ActivePerl-5.10/bin/perl

use strict;
use warnings;
use feature ':5.10';

my $non_zero         = qr{[1-9]};
my $zero             = qr{0};
my $decimal          = qr{[.]};
my $digit            = qr{$non_zero+ | $zero}x;
my $non_zero_natural = qr{$non_zero+ $digit*}x;
my $natural          = qr{$non_zero_natural | $zero}x;
my $integer          = qr{-? $non_zero_natural | $zero}x;
my $real             = qr{$integer (?: $decimal $digit)?}x;

my %number_types = (
    natural => qr/^$natural$/,
    integer => qr/^$integer$/,
    real    => qr/^$real$/
);

for my $n (0, 3.14, -5, 300, "4ever", "-0", "1.2.3") {
    my @types = grep { $n =~ $number_types{$_} } keys %number_types;
    if (@types) {
        say "$n is of type", @types == 1 ? " ": "s ", "@types";
    } else {
        say "$n is not a number";
    }
}

Анонимные подпрограммы, используемые для выделения дублирующего кода:

my $body = sub {
    #some amount of work
};

$body->();
$body->() while $continue;

вместо

#some amount of work
while ($continue) {
    #some amount of work again
}

Таблицы отправки на основе хеша:

my %dispatch = (
    foo => \&foo,
    bar => \&bar,
    baz => \&baz
);

while (my $name = iterator()) {
    die "$name not implemented" unless exists $dispatch{$name};
    $dispatch{$name}->();
}

вместо

while (my $name = iterator()) {
    if ($name eq "foo") {
        foo();
    } elsif ($name eq "bar") {
        bar();
    } elsif ($name eq "baz") {
        baz();
    } else {
        die "$name not implemented";
    }
}
9 голосов
/ 14 марта 2009

Трехстрочные классы с конструкторами, получателями / установщиками и проверкой типов:

{
    package Point;
    use Moose;

    has ['x', 'y'] => (isa => 'Num', is => 'rw');
}

package main;
my $point = Point->new( x => '8', y => '9' );

$point->x(25);
9 голосов
/ 13 марта 2009

Мой любимый пример - реализация Perl факториального калькулятора. В Perl 5 это выглядит так:

use List::Util qw/reduce/;
sub factorial {
    reduce { $a * $b } 1 .. $_[0];
}

Возвращает false, если число <= 1 или строка, и число, если число передано (округление вниз, если дробь). </p>

И с нетерпением жду Perl 6, он выглядит вот так :

sub factorial {
    [*] 1..$^x
}

А также (из блога в ссылке выше) вы можете даже реализовать это как оператор:

sub postfix:<!>(Int $x) {
    [*] 1..($x || 1)
}

и затем используйте его в своем коде так:

my $fact5 = 5!;
7 голосов
/ 13 марта 2009

Если у вас есть список флагов, разделенных запятыми, и вам нужна таблица поиска, все что вам нужно сделать, это:

my %lookup = map { $_ => 1 } split /,/, $flags;

Теперь вы можете просто проверить, какие флаги вам нужны, вот так:

if ( $lookup{FLAG} ) {
    print "Ayup, got that flag!";
}
6 голосов
/ 13 марта 2009

Я удивлен, что никто не упомянул это. Это шедевр по моему мнению:

#!/usr/bin/perl
                                           $==$';
                                         $;||$.| $|;$_
             ='*$ (                  ^@(%_+&~~;# ~~/.~~
         ;_);;.);;#)               ;~~~~;_,.~~,.* +,./|~
    ~;_);@-,  .;.); ~             ~,./@@-__);@-);~~,.*+,.
  /|);;;~~@-~~~~;.~~,.           /.);;.,./@~~@-;.;#~~@-;;
  ;;,.*+,./.);;#;./@,./        |~~~~;#-(@-__@-__&$#%^';$__
   ='`'&'&';$___="````"  |"$[`$["|'`%",';$~=("$___$__-$[``$__"|
              "$___"|       ("$___$__-$[.%")).("'`"|"'$["|"'#").
        '/.*?&([^&]*)&.*/$'.++$=.("/``"|"/$[`"|"/#'").(";`/[\\`\\`$__]//`;"
        |";$[/[\\$[\\`$__]//`;"|";#/[\\\$\\.$__]//'").'@:=("@-","/.",
       "~~",";#",";;",";.",",.",");","()","*+","__","-(","/@",".%","/|",
        ";_");@:{@:}=$%..$#:;'.('`'|"$["|'#')."/(..)(..)/".("```"|"``$["|
        '#("').'(($:{$'.$=.'}<<'.(++$=+$=).')|($:{$'.$=.'}))/'.("```;"|
        "``$[;"|"%'#;").("````'$__"|"%$[``"|"%&!,").${$[};`$~$__>&$=`;$_=
       '*$(^@(%_+&@-__~~;#~~@-;.;;,.(),./.,./|,.-();;#~~@-);;;,.;_~~@-,./.,
        ./@,./@~~@-);;;,.(),.;.~~@-,.,.,.;_,./@,.-();;#~~@-,.;_,./|~~@-,.
          ,.);););@-@-__~~;#~~@-,.,.,.;_);~~~~@-);;;,.(),.*+);;# ~~@-,
           ./|,.*+,.,.);;;);*+~~@-,.*+,.;;,.;.,./.~~@-,.,.,.;_)   ;~~~
             ~@-,.;;,.;.,./@,./.);*+,.;.,.;;@-__~~;#~~@-,.;;,.*   +);;
               #);@-,./@,./.);*+~~@-~~.%~~.%~~@-;;__,. /.);;#@-   __@-
                 __   ~~;;);/@;#.%;#/.;#-(@-__~~;;;.;_ ;#.%~~~~  ;;()
                      ,.;.,./@,.  /@,.;_~~@- ););,.;_   );~~,./  @,.
                      ;;;./@,./|  ~~~~;#-(@- __,.,.,.    ;_);~~~ ~@
                       -~~());;   #);@-,./@,  .*+);;;     ~~@-~~
                       );~~);~~  *+~~@-);-(   ~~@-@-_      _~~@-
                       ~~@-);;   #,./@,.;.,    .;.);@      -~~@-;
                       #/.;#-(   ~~@-@-__      ~~@-~~       @-);@
                       -);~~,    .*+,./       |);;;~        ~@-~~
                        ;;;.;     _~~@-@     -__);.         %;#-(
                        @-__@      -__~~;#  ~~@-;;          ;#,.
                        ;_,..         %);@-,./@,            .*+,
                        ..%,           .;.,./|)             ;;;)
                        ;;#~            ~@-,.*+,.           ,.~~
                       @-);            *+,.;_);;.~         ~););
                      ~~,.;         .~~@-);~~,.;.,         ./.,.;
                      ;,.*+        ,./|,.);  ~~@-         );;;,.(
                    ),.*+);                              ;#~~/|@-
                  __~~;#~~                                $';$;;
3 голосов
/ 16 марта 2009

Я абсолютно люблю Черный Perl (ссылка на версию, переписанную для компиляции под Perl 5). Он компилируется, но, насколько я могу судить, он на самом деле ничего не делает.

Это то, что вы получаете за язык, написанный лингвистом, с прагматической точки зрения, а не с теоретической точки зрения.

Переходя от этого, вы можете думать о Perl, на который люди жалуются как на pidgin Perl (совершенно полезный, но не выразительный, и остерегаться попыток выразить в нем что-то сложное), и материал, о котором говорит @pjf как «правильный» Perl, язык Шекспира, Хемингуэя, Юма и так далее. [править: ошибаться, хотя его легче читать, чем Хьюма, и менее устарело, чем Шекспира.] [переиздать и, надеюсь, менее алкоголично, чем Хемингуэй]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...