Варсик
545 EGP
    Рейтинг канала: 4(81) Репутация: 117 Сообщения: 4041 Откуда: Москва Зарегистрирован: 22.12.2002
 |
|
Решил открыть тут этот топик... Начнем, пожалуй.
Знаете-ли вы что: Постфиксная запись (одна из фишек Перла), не только выглядит более читабельно для простого человека, но и не генерирует лишнего скоупа, а потому чуть эффективней:
Пояснения (кликните здесь для просмотра)
Код: |
warstone@dev:~$ perl -MO=Concise,-exec -e 'my $a = 0;
for(1..100){
$a++;
}'
1 <0> enter
2 <;> nextstate(main 1 -e:1) v:{
3 <$> const(IV 0) s
4 <0> padsv[$a:1,4] sRM*/LVINTRO
5 <2> sassign vKS/2
6 <;> nextstate(main 4 -e:2) v:{
7 <0> pushmark s
8 <$> const(IV 1) s
9 <$> const(IV 100) s
a <$> gv(*_) s
b <{> enteriter(next->f last->i redo->c) lKS/8
g <0> iter s
h <|> and(other->c) vK/1
c <;> nextstate(main 2 -e:3) v #nextstate не создается
d <0> padsv[$a:1,4] sRM
e <1> preinc[t4] vK/1
f <0> unstack v
goto g
i <2> leaveloop vK/2
j <@> leave[1 ref] vKP/REFC
-e syntax OK
warstone@dev:~$ perl -MO=Concise,-exec -e 'my $a = 0;
$a++ for 1..100;'
1 <0> enter
2 <;> nextstate(main 1 -e:1) v:{
3 <$> const(IV 0) s
4 <0> padsv[$a:1,2] sRM*/LVINTRO
5 <2> sassign vKS/2
6 <;> nextstate(main 2 -e:2) v:{
7 <0> pushmark s
8 <$> const(IV 1) s
9 <$> const(IV 100) s
a <$> gv(*_) s
b <{> enteriter(next->e last->h redo->c) lKS/8
f <0> iter s
g <|> and(other->c) vK/1 #вот тут
c <0> padsv[$a:1,2] sRM
d <1> preinc[t2] vK/1
e <0> unstack v
goto f
h <2> leaveloop vK/2
i <@> leave[1 ref] vKP/REFC
-e syntax OK |
|
-----
Знаете-ли вы что: безопасный вызов процедуры через can:
Код: |
my $sub = Package->can("sub");
$sub->() if defined $sub; |
Медленнее чем eval?
Benchmark (кликните здесь для просмотра)
Код: |
warstone@dev:~$ cat b.pl
#!/usr/bin/perl
package Test;
sub test { return 1; }
package main;
use Benchmark qw(:all);
my $runs = 10000000;
timethese($runs, {
'can' => t_can,
'eval' => t_eval,
});
sub t_can {
my $sub = Test->can('test');
$sub->() if defined $sub;
}
sub t_eval {
eval {
Test::test();
};
}
warstone@dev:~$ perl b.pl
Benchmark: timing 10000000 iterations of can, eval...
can: 7 wallclock secs ( 5.94 usr + 0.00 sys = 5.94 CPU) @ 1683501.68/s (n=10000000)
eval: 3 wallclock secs ( 2.39 usr + 0.00 sys = 2.39 CPU) @ 4184100.42/s (n=10000000) |
|
Если грубо, то это вызвано тем, что can проверяет 100500 вариантов и экзотики, а eval просто "выполняет код". Кстати, в perl 5.22 (который выйдет довольно скоро) проблема станет не актуальна.
-----
Знаете-ли вы что: Запись package XXX которую мы пишем в каждом пакете - это не более чем сокращение записи. Процедуру в пакете можно объявить и так:
Код: |
sub Test::test {
print "This is sub in module Test\n";
} |
Собственно сам пакет - это, в первом приближении, не более чем хеш функций и переменных, называемый стэшом. И к нему есть доступ. Из-за этого можно в рантайме поменять наследование, допустим, и это будет работать:
Cкрытый текст (кликните здесь для просмотра)
Код: |
warstone@dev:~$ cat test.pl
#!/usr/bin/perl
sub Test::test {
print "This is sub in module Test\n";
}
sub Test2::test0 {
print "This is sub in module Test2\n";
}
Test::test();
my $obj = bless {}, Test;
$obj->test();
eval {
$obj->test0();
}; if ($@){ print ">> $@" }
push(@{"Test::ISA"}, 'Test2');
$obj->test0();
warstone@dev:~$ perl test.pl
This is sub in module Test
This is sub in module Test
>> Can't locate object method "test0" via package "Test" at test.pl line 16.
This is sub in module Test2 |
|
Собственно на этом принципе строятся почти все ORM'ы (В частности DBIx::Class), которые умеют генерировать классы из схемы БД, например.
_________________ WARNING: By reading this post you accept that this post is genius. |