- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
package Exception;
sub new {
my($package, $what) = @_;
return bless { what => $what }, $package;
}
sub what {
my($self) = @_;
return $self->{what};
}
package main;
sub try(&$) {
my($code, $catch) = @_;
unless(eval { $code->(); 1 }) {
local $_ = $@;
$catch->();
}
}
sub catch(&) { $_[0] }
sub throw($) { die $_[0] }
try {
throw new Exception("Ошибка");
} catch {
print $_->what;
};
http://search.cpan.org/~doy/Try-Tiny-0.16/lib/Try/Tiny.pm
http://search.cpan.org/~pjordan/Exception-1.7/Exception.pm
http://search.cpan.org/~drolsky/Exception-Class-1.37/lib/Exception/Class.pm
Тысячи их.
inb4 а изкоробочных - да, нету.
это слегка неправильно обобщение.
в перле нету штатного try/catch/finally *синтакса*.
но его можно самому реализовать.
все приведеное выше есть чистой воды syntax sugar вокруг `eval {};` (эквивалент `try {}`), `die $smth` (эквивалент `throw smth`) и `if ($@) {}` (эквивалент `catch (e) {}`).
причина почему не добавляют выделеный синтакс (по крайней мере причина которую я слышал много лет назад) заключается в том что `eval {}` очень медленный и как следствие эксепшены будут весьма заметно тормозить. (и в добавок, только недавно начали реализовывать переменные $@/$!/etc как thread-local. и я не уверен что закончили. в типичном перле это глобальные переменные.)
вообщем, в перле есть эксепшены, только у них слегка кривой синтакс потому что их реализовали более или менее случайно, и они не рекомендуются потому что подтормаживают (и не поддерживают многопоточность).
Но то что занимает 30 строк кода на "реализовать самому" тоже не тянет.
Я давеча пулы к паре фактори в жабе прикручивал. Официально 0% "реализовал сам" - строго апачевы пулы, но ~200 кода понадобилось.
Как по мне, я предпочитаю 100% "сделай сам" в 30 строк, нежели чем 0% "сделай сам" но в 200 строк.
- Предоставляются по умолчанию самим языком, или в виде библиотеки, созданной сторонними разработчиками?
- Но не в языке ведь из коробки. :) Потому и ~200 строк кода. Потому что это "реализовать самому". А вот если бы оно было из коробки - было бы всё как надо.
Единственное что язык может сделать, это позволять расширения в (насколько только возможно) безболезненной и прозрачной форме.
В случае с перлом и исключениями - исключений из коробки в перле не появляется после создания расширения одним из потребителей языка. И изкоробочных исключений в перле всё ещё нет.
Понятно, что в перле самому реализовать исключения - раз плюнуть. И так же просто эту реализацию будет использовать. Но она всё равно получается не более, чем сторонней.
Перл был хорошим языком для того, для чего его задумали - парсинга stdin регулярками и вывода в stdout. Универсальный язык из него вышел вообще никакой.
НЕ НУЖЕН
PERL скорее сделает невозможное, чем выдаст сообщение об ошибке. Ваша программа заработает сразу же и будет работать всегда, не вызывая сообщений об ошибках, только насколько правильно – это, как говорится, "тонкий философский вопрос". (Хотя это и к php подходит)
I_hate_PERL_-_what_a_tricky_language;
Секрет прост – слова, не поддающиеся никакой интерпретации, PERL считает строками, заключенными в кавычки, в результате чего получается выражение, а это уже допустимый оператор, о как! Таким образом можно, например, вызвать несуществующую процедуру, просто опечатавшись при наборе ее имени, и потратить много-много часов на отладку неработающего фрагмента – ведь вы не дождетесь от PERL сообщения об ошибке или хотя бы предупреждения ни на этапе компиляции, ни на этапе выполнения, так что ошибку придется искать самостоятельно.
При чем тут мой код?
>Нормально написанный код на перле смотрится как говнокод!
Например:
Этот код показывает разницу в 20 раз на Perl 5.14. Однако, если мы добавим в процедуру простейшую арифметическую операцию с переменной, то разница сократится уже до 2-х раз.
с простой функцией разница меньше:
и на последок:
Ну 20% потерь для такого простого тела это очень даже хорошо. На более-менее сложной функции станет совсем незаметно. А если там внутри этого eval'а какое-нибудь чтение файла, то и совсем в пределах погрешности.
А вот eval { 1 } и eval "1" бенчить глупо. Надо на чем-то более-менее реалистичном, чем возврат true. Тогда разница будет поменьше на порядки...
P.S. Это я все к чему - если юзать eval во внутренних циклах текстодробилки - да, тормозит. А если для обработки ошибок в каком-нибудь движке для сайта, то 146%, что никакой разницы никто не заметит.
> только недавно начали реализовывать переменные $@/$!/etc как thread-local
О_о. Т.е. сделали треды, но забыли сделать инфу об ошибках thread-local? Пиздец, приехали. Хотя и в libc когда-то такая же херня творилась с errno. Не учится автор пёрла на чужих ошибках ;)
Но если бы я запостил столько говна никто бы не стал разбираться.