Подтвердить что ты не робот

Каковы некоторые изящные функции или использование Perl?

Что? Perl Beautiful? Elegant? Он, должно быть, шутит!

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

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

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

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

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

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

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

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

4b9b3361

Ответ 1

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

my $result = $obj->method(
    flux_capacitance       => 23,
    general_state          => 'confusion',
    attitude_flags         => ATTITUDE_PLEASANT | ATTITUDE_HELPFUL,
);

Ответ 2

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

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

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

Все самое лучшее,

Пол

Ответ 3

Я удивлен, что никто не упомянул Schwartzian Transform.

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

И в отсутствие оператора slurp,

my $file = do { local $/; readline $fh };

Ответ 4

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

@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) можно использовать, чтобы сделать код короче, сохраняя при этом его очень читабельность.

Ответ 5

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

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";
    }
}

Ответ 6

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

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

Это возвращает false, если число равно <= 1 или строка и число, если число передано (округление вниз, если фракция).

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

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

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

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

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

my $fact5 = 5!;

Ответ 7

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

{
    package Point;
    use Moose;

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

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

$point->x(25);

Ответ 8

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

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

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

if ( $lookup{FLAG} ) {
    print "Ayup, got that flag!";
}

Ответ 9

Я удивлен, что никто не упомянул об этом. Это шедевр , на мой взгляд:

#!/usr/bin/perl
                                           $==$';
                                         $;||$.| $|;$_
             ='*$ (                  ^@(%_+&~~;# ~~/.~~
         ;_);;.);;#)               ;~~~~;_,.~~,.* +,./|~
    ~;_);@-,  .;.); ~             ~,./@@-__);@-);~~,.*+,.
  /|);;;[email protected]~~~~;.~~,.           /.);;.,./@[email protected];.;#[email protected];;
  ;;,.*+,./.);;#;./@,./        |~~~~;#-(@[email protected]__&$#%^';$__
   ='`'&'&';$___="````"  |"$[`$["|'`%",';$~=("$___$__-$[``$__"|
              "$___"|       ("$___$__-$[.%")).("'`"|"'$["|"'#").
        '/.*?&([^&]*)&.*/$'.++$=.("/``"|"/$[`"|"/#'").(";`/[\\`\\`$__]//`;"
        |";$[/[\\$[\\`$__]//`;"|";#/[\\\$\\.$__]//'").'@:=("@-","/.",
       "~~",";#",";;",";.",",.",");","()","*+","__","-(","/@",".%","/|",
        ";_");@:{@:}=$%..$#:;'.('`'|"$["|'#')."/(..)(..)/".("```"|"``$["|
        '#("').'(($:{$'.$=.'}<<'.(++$=+$=).')|($:{$'.$=.'}))/'.("```;"|
        "``$[;"|"%'#;").("````'$__"|"%$[``"|"%&!,").${$[};`$~$__>&$=`;$_=
       '*$(^@(%_+&@-__~~;#[email protected];.;;,.(),./.,./|,.-();;#[email protected]);;;,.;[email protected],./.,
        ./@,./@[email protected]);;;,.(),.;[email protected],.,.,.;_,./@,.-();;#[email protected],.;_,./|[email protected],.
          ,.);););@[email protected]__~~;#[email protected],.,.,.;_);[email protected]);;;,.(),.*+);;# [email protected],
           ./|,.*+,.,.);;;);*[email protected],.*+,.;;,.;.,./[email protected],.,.,.;_)   ;~~~
             [email protected],.;;,.;.,./@,./.);*+,.;.,.;;@-__~~;#[email protected],.;;,.*   +);;
               #);@-,./@,./.);*[email protected]~~.%~~.%[email protected];;__,. /.);;#@-   [email protected]
                 __   ~~;;);/@;#.%;#/.;#-(@-__~~;;;.;_ ;#.%~~~~  ;;()
                      ,.;.,./@,.  /@,.;[email protected] ););,.;_   );~~,./  @,.
                      ;;;./@,./|  ~~~~;#-(@- __,.,.,.    ;_);~~~ [email protected]
                       -~~());;   #);@-,./@,  .*+);;;     [email protected]~~
                       );~~);~~  *[email protected]);-(   [email protected]@-_      [email protected]
                       [email protected]);;   #,./@,.;.,    .;.);@      [email protected];
                       #/.;#-(   [email protected]@-__      [email protected]~~       @-);@
                       -);~~,    .*+,./       |);;;~        [email protected]~~
                        ;;;.;     [email protected]@     -__);.         %;#-(
                        @[email protected]      -__~~;#  [email protected];;          ;#,.
                        ;_,..         %);@-,./@,            .*+,
                        ..%,           .;.,./|)             ;;;)
                        ;;#~            [email protected],.*+,.           ,.~~
                       @-);            *+,.;_);;.~         ~););
                      ~~,.;         [email protected]);~~,.;.,         ./.,.;
                      ;,.*+        ,./|,.);  [email protected]         );;;,.(
                    ),.*+);                              ;#~~/|@-
                  __~~;#~~                                $';$;;

Ответ 10

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

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

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

Ответ 11

Добавляя к любви map и grep, мы можем написать простой синтаксический анализатор командной строки.

my %opts = map { $_ => 1 } grep { /^-/ } @ARGV;

Если мы хотим, мы можем установить для каждого флага индекс в @ARGV:

my %opts = map { $ARGV[$_] => $_ } grep { $ARGV[$_] =~ /^-/ } 0 .. $#ARGV;

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

if( defined( $opts{-e} ) ) {
  my $arg = $ARGV[ $opts{-e} ];
  # do -e stuff for $arg
}

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

Если вам не нравится, как долго некоторые из этих строк, вы всегда можете использовать промежуточные переменные или просто удобные разрывы строк (эй, фанатики Python? Вы слышите это? Мы можем поместить одну строку кода в две строки, и это все еще работает!), чтобы он выглядел лучше:

my %opts = map  { $ARGV[$_] => $_   }
           grep { $ARGV[$_] =~ /^-/ } 0 .. $#ARGV;

Ответ 12

Этот механизм синтаксического анализа данных является компактным и простым в настройке (пропустить пустые строки, пропустить строки, начинающиеся с X и т.д.).

open(H_CONFIG, "< $file_name") or die("Error opening file: $file_name! ($!)");
while (<H_CONFIG>)
{
   chomp;         # remove the trailing newline
   next if $_ =~ /^\s*$/; # skip lines that are blank
   next if $_ =~ /^\s*#/; # skip lines starting with comments
   # do something with the line
}

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

Ответ 13

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

my $string = 1 . 2;
my $number = "1" + "2";
my $unambiguous = 1 . "2";

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

var string = "1" + "2";
var number = 1 + 2;
var ambiguous = 1 + "2";

Или для динамических языков, таких как Python и Ruby, которые требуют принуждения типа между строками и числовыми значениями.

string = "1" + "2"
number = 1 + 2
throws_exception = 1 + "2"

По-моему, Perl делает это так правильно, а другие языки ошибочны.

Ответ 14

Более бедные машинистки вроде меня, которые слишком часто нажимают на клавиши переключения передач и имеют почти иррациональный страх использования точки с запятой, начали писать наш код Perl в отформатированных файлах python.:)

например.

>>> k = 5
>>> reduce(lambda i,j: i*j, range(1,k+1),1)
120
>>> k = 0
>>> reduce(lambda i,j: i*j, range(1,k+1),1)
1