Если observableOne
может иметь только одну подписку, вы можете сделать это несколькими способами. Самый простой способ - ввести Subject
; он будет подписан на observableOne
, а все остальные подписчики подпишутся на тему:
PublishSubject<DataType> observableOneStream = PublishSubject.create();
observableOne
.subscribe( observableOneStream );
...
observableOneStream.subscribe( firstSubscription );
...
observableOneStream.subscribe( secondSubscription );
Perl упрощает использование списков/хешей для реализации названный параметрами, которые я считаю очень изящными и огромная помощь самодокументированию кода.
my $result = $obj->method(
flux_capacitance => 23,
general_state => 'confusion',
attitude_flags => ATTITUDE_PLEASANT | ATTITUDE_HELPFUL,
);
Мои любимые части изящного кода Perl не обязательно изящны вообще. Они метаизящны и позволяют Вам избавляться от всех тех дурных привычек, в которые проскользнули многие разработчики Perl. Мне потребовались бы часы или дни, чтобы показать им всем в деталях, которых они заслуживают, но как короткий список они включают:
or die...
конструкция). См., что также мои автоумирают видео блога и ). , Если Вы слишком ленивы, чтобы перейти по ссылкам, я недавно сделал разговор в Linux.conf.au о большей части вышеупомянутого. Если Вы пропустили его, существует видео его онлайн (ogg theora). Если Вы слишком ленивы для просмотра видео, я делаю, значительно расширенная версия разговора как учебное руководство в OSCON в этом году (дал право делающее право Perl ).
Всего самого лучшего,
Paul
Классы с тремя линиями с конструкторами, методом get/методами set и вводят проверку:
{
package Point;
use Moose;
has ['x', 'y'] => (isa => 'Num', is => 'rw');
}
package main;
my $point = Point->new( x => '8', y => '9' );
$point->x(25);
Я абсолютно любовь Черный Perl (связываются с версией, переписанной для компиляции под Perl 5). Это компилирует, но насколько я могу сказать, что это ничего на самом деле не делает.
Это - то, что Вы получаете для языка, записанного лингвистом из прагматической перспективы, а не с теоретической точки зрения.
Хождение дальше, от которого, можно думать о Perl, что люди жалуются на как Perl гибридного языка (совершенно полезный, но не выразительный, и остерегаются попытки выразить что-либо сложное в нем), и материал, что @pjf говорит почти как "надлежащий" Perl, язык Shakespeare, Hemingway, Hume и так далее. [редактирование: допустите ошибку, хотя легче для чтения, чем Hume и менее датированный, чем Shakespeare.] [переиздают и надо надеяться менее алкогольный, чем Hemingway]
Более бедные машинистки как я, которые заболели судорогами, поражающими клавишу Shift слишком часто, и имеют почти безрассудный страх использования точки с запятой, начали писать наш код 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
Я удивлен, что никто не упомянул, что Schwartzian Преобразовывают.
my @sorted =
map { $_->[0] }
sort { $a->[1] <=> $b->[1] }
map { [ $_, expensive_func($_) ] }
@elements;
И в отсутствие хлебать оператора,
my $file = do { local $/; readline $fh };
Имеет список файлов пользователя, хочет, чтобы Ваша программа обработала? Не хотите случайно обрабатывать программу, папку или несуществующий файл? Попробуйте это:
@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: $_";
}
}
grep
(и map
) может использоваться для создания кода короче, все еще сохраняя это очень читаемым.
"Или умирают" конструкция:
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";
}
}
Любимым моим примером является реализация 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!;
Если Вы имеете список разделенных запятой значений флагов и хотите справочную таблицу для них, все, что необходимо сделать:
my %lookup = map { $_ => 1 } split /,/, $flags;
Теперь можно просто протестировать, для которых флагов Вам нужно как так:
if ( $lookup{FLAG} ) {
print "Ayup, got that flag!";
}
Я удивлен, что никто не упомянул это. Это - шедевр, по-моему:
#!/usr/bin/perl $==$'; $;||$.| $|;$_ ='*$ ( ^@(%_+&~~;# ~~/.~~ ;_);;.);;#) ;~~~~;_,.~~,.* +,./|~ ~;_);@-, .;.); ~ ~,./@@-__);@-);~~,.*+,. /|);;;~~@-~~~~;.~~,. /.);;.,./@~~@-;.;#~~@-;; ;;,.*+,./.);;#;./@,./ |~~~~;#-(@-__@-__&$#%^';$__ ='`'&'&';$___="````" |"$[`$["|'`%",';$~=("$___$__-$[``$__"| "$___"| ("$___$__-$[.%")).("'`"|"'$["|"'#"). '/.*?&([^&]*)&.*/$'.++$=.("/``"|"/$[`"|"/#'").(";`/[\\`\\`$__]//`;" |";$[/[\\$[\\`$__]//`;"|";#/[\\\$\\.$__]//'").'@:=("@-","/.", "~~",";#",";;",";.",",.",");","()","*+","__","-(","/@",".%","/|", ";_");@:{@:}=$%..$#:;'.('`'|"$["|'#')."/(..)(..)/".("```"|"``$["| '#("').'(($:{$'.$=.'}<<'.(++$=+$=).')|($:{$'.$=.'}))/'.("```;"| "``$[;"|"%'#;").("````'$__"|"%$[``"|"%&!,").${$[};`$~$__>&$=`;$_= '*$(^@(%_+&@-__~~;#~~@-;.;;,.(),./.,./|,.-();;#~~@-);;;,.;_~~@-,./., ./@,./@~~@-);;;,.(),.;.~~@-,.,.,.;_,./@,.-();;#~~@-,.;_,./|~~@-,. ,.);););@-@-__~~;#~~@-,.,.,.;_);~~~~@-);;;,.(),.*+);;# ~~@-, ./|,.*+,.,.);;;);*+~~@-,.*+,.;;,.;.,./.~~@-,.,.,.;_) ;~~~ ~@-,.;;,.;.,./@,./.);*+,.;.,.;;@-__~~;#~~@-,.;;,.* +);; #);@-,./@,./.);*+~~@-~~.%~~.%~~@-;;__,. /.);;#@- __@- __ ~~;;);/@;#.%;#/.;#-(@-__~~;;;.;_ ;#.%~~~~ ;;() ,.;.,./@,. /@,.;_~~@- ););,.;_ );~~,./ @,. ;;;./@,./| ~~~~;#-(@- __,.,.,. ;_);~~~ ~@ -~~());; #);@-,./@, .*+);;; ~~@-~~ );~~);~~ *+~~@-);-( ~~@-@-_ _~~@- ~~@-);; #,./@,.;., .;.);@ -~~@-; #/.;#-( ~~@-@-__ ~~@-~~ @-);@ -);~~, .*+,./ |);;;~ ~@-~~ ;;;.; _~~@-@ -__);. %;#-( @-__@ -__~~;# ~~@-;; ;#,. ;_,.. %);@-,./@, .*+, ..%, .;.,./|) ;;;) ;;#~ ~@-,.*+,. ,.~~ @-); *+,.;_);;.~ ~);); ~~,.; .~~@-);~~,.;., ./.,.; ;,.*+ ,./|,.); ~~@- );;;,.( ),.*+); ;#~~/|@- __~~;#~~ $';$;;
Добавление к любви к 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;
Этот механизм анализа файлов компактен и прост в настройке (пропускать пустые строки, пропускать строки, начинающиеся с 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-файлы или собрать информацию о каталоге для ' умная сборка ».