DSLs в Perl
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

DSLs в Perl

on

  • 534 views

Технология реализации DSL в Perl без использования Devel::Declare. О том как это работает и какие трюки Perl можно ...

Технология реализации DSL в Perl без использования Devel::Declare. О том как это работает и какие трюки Perl можно использовать.

Statistics

Views

Total Views
534
Views on SlideShare
534
Embed Views
0

Actions

Likes
0
Downloads
0
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

DSLs в Perl Presentation Transcript

  • 1. DSLs в Perl Как? Руслан Закиров <ruz@bestpractical.com> <ruz@bestpractical.com> Best Practical Solutions, 2008
  • 2. Что?
  • 3. under 'user/*' => run { my $u = U->load($1); ... }
  • 4. under 'user/*' => run { … abort(404) unless $u; on 'profile' => run {}; on 'stats' => run {}; on 'blog' => run {}; }
  • 5. Зачем?
  • 6. Выразительно
  • 7. Управляемо
  • 8. Как?
  • 9. Прототипы
  • 10. Прототипы ($) (&) (@)
  • 11. Прототипы (завтрак) sub set($$) {...} set key => $val;
  • 12. Прототипы (запястья) ()
  • 13. Прототипы (&) блок функция
  • 14. Прототипы grep {} @_ sub grep(&@) {}
  • 15. Методы
  • 16. Методы $o = new X k => $v;
  • 17. Методы perl -e 'title is „foo”;'
  • 18. Методы Невозможно найти метод "title" в пакете "is"
  • 19. Методы может вмы забыли загрузить "is"?
  • 20. Методы этап исполнения
  • 21. Методы perl -e 'sub foo { title is „foo” }' нет ошибки
  • 22. Методы my $a = {}; local *is::AUTOLOAD = sub { shift; # is $a->{$AUTLOAD} = join ' ', @_ }; $call->(); # что-то
  • 23. Объединим
  • 24. Объеденим (img_simple.pl) sub img(&) { my $code = shift; my %attr; local *is::AUTOLOAD = sub {...}; $code->(); my $attrs = join ' ', map $_.'=”'.$attr{$_}, keys %attr; print „<img $attrs />”; }
  • 25. Слишком просто?
  • 26. Усложним (img_strict.pl) my %attr_checks = ( img => { _mandatory => [qw(src alt)], src => { canonicalizer => sub {...}, provides => sub {...}, }, # ... }, );
  • 27. Усложним (img_strict.pl) canonicalizer => sub { return "/static/images/$_[0]" unless $_[0] =~ /^//; return $_[0]; }
  • 28. Усложним (img_strict.pl) provides => sub { return unless my ($w, $h) = ($_[0] =~ /-(d+)x(d+)./); return (width => $w, height => $h); }
  • 29. Результат (img_strict.pl) img { alt is 'feed', src is 'f-14x14.png' };
  • 30. Результат (img_strict.pl) <img width="14" height="14" alt="feed" src="/s/i/f-14x14.png" />
  • 31. Отладка
  • 32. Отладка (carp.pl) нет атрибута 'boo' у тега 'img' at carp.pl line 10
  • 33. Отладка (carp.pl) local $Carp::CarpLevel = 1; Carp::croak(...);
  • 34. Отладка (carp.pl) нет атрибута 'boo' у тега 'img' at carp.pl line 16 место вызова
  • 35. Отладка (carp.pl) main::__ANON__() main::__ANON__() called at carp.pl line 13
  • 36. Отладка (carp.pl) sub img(&) { local *__ANON__ = "img_impl"; ... }
  • 37. Отладка (carp.pl) bla-bla at carp.pl line 17 main::img_impl() called at... main::img_impl() main::img('CODE(...)') called at...
  • 38. Грабли №1
  • 39. Грабли №1 page {...}; sub page(&) {...};
  • 40. Грабли №1 Невозможно вызвать метод "page" без пакета или объекта
  • 41. Грабли №2
  • 42. Грабли №2 sub page(&) { local *title::page = sub {} shift->(); }; page { page title „qwe” };
  • 43. Грабли №2 Методы проигрывают протипам
  • 44. Избавляемся от методов
  • 45. Без методов (wo_methods.pl) our %ATTR; sub attrs(&) { %ATTR = shift->() } sub img(&) { local %ATTR; $code->(); ... }
  • 46. Без методов (wo_methods.pl) img { attrs { alt => 'boo', src => 'href' } };
  • 47. Вложенные структуры
  • 48. Вложения (div_simple.pl) <div><div> что-то </div></div>
  • 49. Вложения (div_simple.pl) sub div(&) { my $code = shift; my $inside = $code->(); return "<div>$inside</div>"; } print div { div {'some'} };
  • 50. Если что-то сложнее?
  • 51. Усложняем div { div {1};div{2} };
  • 52. Усложняем <div> <div>2</div> </div>
  • 53. Усложняем Фигня вышла
  • 54. Простое решение
  • 55. Простое решение (div_sol1.pl) sub div(&) { my $code = shift; my @inside = $code->(); return "<div>@inside</div>"; }
  • 56. Простое решение (div_sol1.pl) print div { div {1}, div {2} }, div { div {3}, div {4} };
  • 57. Код не вставишь :(
  • 58. явный print отстой
  • 59. запятые в топку
  • 60. Да прибудут с вами контексты
  • 61. Контексты (context1.pl) unless ( defined wantarray ) { # void } elsif ( wantarray ) { # array } else { # scalar }
  • 62. Контексты sub div(&) { my $res = join '', shift->(); unless ( defined wantarray ) { print „<div>$res</div>”; } else { return „<div>$res</div>”; } }
  • 63. Контексты (context1.pl) div { div {1}; div {2} }; <div>1</div> <div><div>2</div></div>
  • 64. Буферизация
  • 65. Бу-эфиры (buffers1.pl) sub buffered { my $buf = ''; local *STDOUT; open STDOUT, '>', $buf; return $buf . join('', shift->()); }
  • 66. Бу-эфиры (buffers1.pl) sub div(&) { my $res = buffered(shift); return „<div>$res</div>” if defined wantarray; print „<div>$res</div>”; }
  • 67. Бу-эфиры (buffers1.pl) div { div{'menu'}; my $some = 'some'; div{$some}, div{'tail'} };
  • 68. ЯХУ! :)
  • 69. Грабли №3
  • 70. Грабли №3 div { 'some'; my $some = 'some'; div{$some} };
  • 71. Грабли №3 print 'some'; outs('some'); x {'some'} { my $x=...; 'some', div{$x} }
  • 72. Установка функций
  • 73. Установка функций my @tags = qw(a b); foreach my $t ( @tags ) { no strict 'refs'; *{'main::'.$t} = sub (&) { ... }; }
  • 74. Установка функций sub import; Exporter; Symbol; И прочие
  • 75. Прото-цепочки
  • 76. Это не химия И не биология
  • 77. Это (&;$)
  • 78. Прото-цепочки sub a(&;$) { print 'a ', context wantarray, "n" } sub b(&;$) { print 'b ', context wantarray, "n" }
  • 79. Прото-цепочки a {} b {}; b scalar a void
  • 80. Промежуточное прдставление
  • 81. Пром-представления *{'main::'.$t} = sub (&;$) { my ($code, $next) = @_; unless ( defined wantarray ) { return _tag($t, $code, $next); } else { return bless sub { return _tag($t, $code, $next) }, 'MyTag'; } };
  • 82. Пром-представления package MyTag; use overload '""' => sub { return buffered($_[0]) }; 1;
  • 83. Пром-представления a {'head'} b {'middle'} c {'tail'}; im_represent.pl
  • 84. Экранирование
  • 85. Экранирование sub _escape { return unless defined $_[0]; my $v = shift; $v = „$v”; „$v”; $v =~ s/.../.../g; return $v; }
  • 86. Экранирование sub escape(@_) { return map blessed($_) && $_->isa('MyTag') ? $_ : _escape($_), @_; }
  • 87. Экранирование sub buffered { ... return join '', $buf, escape(@tail); } sub _tag { my ($tag, $code, $next) = @_; ... print join '', $res, escape $next; }
  • 88. Все работает escaping.pl
  • 89. На закуску к экранам sub outs(@) { print _escape(join '', @_) } sub raw(@) { print join '', @_ } # грабли №3 div { outs('some'); div {...} };
  • 90. MyTD готов. Осталось только...
  • 91. Недостающие части объединить все примеры запаковать все sub template($$); # template 'index' => run {}; sub show($@); # show 'index', arg => $arg, ...;
  • 92. Посмотреть Template::Declare Jifty::Dispatcher Jifty::Param::Schema Jifty::DBI::Schema Object::Declare B::*
  • 93. ВСЕ
  • 94. Вопросы?