SlideShare ist ein Scribd-Unternehmen logo
1 von 94
Downloaden Sie, um offline zu lesen
DSLs в Perl




    Как?

Руслан Закиров <ruz@bestpractical.com>
               <ruz@bestpractical.com>
           Best Practical Solutions, 2008
Что?
under 'user/*' => run {
  my $u = U->load($1);
  ...
}
under 'user/*' => run {
  …
  abort(404) unless $u;
  on 'profile' => run {};
  on 'stats' => run {};
  on 'blog' => run {};
}
Зачем?
Выразительно
Управляемо
Как?
Прототипы
Прототипы



 ($)
 (&)
 (@)
Прототипы (завтрак)




sub set($$) {...}
set key => $val;
Прототипы (запястья)




        ()
Прототипы



  (&)
 блок
функция
Прототипы




  grep {} @_
sub grep(&@) {}
Методы
Методы




$o = new X k => $v;
Методы




perl -e 'title is „foo”;'
Методы



 Невозможно найти
метод "title" в пакете
         "is"
Методы




может вмы забыли
 загрузить "is"?
Методы




этап исполнения
Методы



perl -e 'sub foo { title
       is „foo” }'
      нет ошибки
Методы


my $a = {};
local *is::AUTOLOAD = sub {
  shift; # is
  $a->{$AUTLOAD} = join ' ', @_
};
$call->(); # что-то
Объединим
Объеденим (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 />”;
}
Слишком просто?
Усложним (img_strict.pl)
my %attr_checks = (
   img => {
      _mandatory => [qw(src alt)],
      src => {
         canonicalizer => sub {...},
         provides => sub {...},
      },
      # ...
   },
);
Усложним (img_strict.pl)


canonicalizer => sub {
  return "/static/images/$_[0]"
   unless $_[0] =~ /^//;
  return $_[0];
}
Усложним (img_strict.pl)


provides => sub {
   return unless my ($w, $h) =
    ($_[0] =~ /-(d+)x(d+)./);
   return (width => $w, height => $h);
}
Результат (img_strict.pl)


img {
 alt is 'feed',
 src is 'f-14x14.png'
};
Результат (img_strict.pl)
<img
 width="14"
 height="14"
 alt="feed"
 src="/s/i/f-14x14.png"
/>
Отладка
Отладка (carp.pl)


  нет атрибута
'boo' у тега 'img'
at carp.pl line 10
Отладка (carp.pl)




local $Carp::CarpLevel = 1;
Carp::croak(...);
Отладка (carp.pl)

  нет атрибута
'boo' у тега 'img'
at carp.pl line 16
  место вызова
Отладка (carp.pl)




  main::__ANON__()
  main::__ANON__()
called at carp.pl line 13
Отладка (carp.pl)

sub img(&) {
  local *__ANON__
    = "img_impl";
...
}
Отладка (carp.pl)



bla-bla at carp.pl line 17
main::img_impl() called at...
main::img_impl()
main::img('CODE(...)') called at...
Грабли №1
Грабли №1




page {...};
sub page(&) {...};
Грабли №1



Невозможно вызвать
 метод "page" без
пакета или объекта
Грабли №2
Грабли №2


sub page(&) {
  local *title::page = sub {}
  shift->();
};
page { page title „qwe” };
Грабли №2


   Методы
проигрывают
  протипам
Избавляемся от
   методов
Без методов (wo_methods.pl)
our %ATTR;
sub attrs(&) {
  %ATTR = shift->()
}
sub img(&) {
  local %ATTR;
  $code->();
  ...
}
Без методов (wo_methods.pl)



img { attrs {
 alt => 'boo', src => 'href'
} };
Вложенные
структуры
Вложения (div_simple.pl)


 <div><div>
   что-то
</div></div>
Вложения (div_simple.pl)

sub div(&) {
   my $code = shift;
   my $inside = $code->();
   return "<div>$inside</div>";
}
print div { div {'some'} };
Если что-то
 сложнее?
Усложняем


div {
 div {1};div{2}
};
Усложняем


<div>
<div>2</div>
</div>
Усложняем




Фигня вышла
Простое решение
Простое решение (div_sol1.pl)


sub div(&) {
  my $code = shift;
  my @inside = $code->();
  return "<div>@inside</div>";
}
Простое решение (div_sol1.pl)




print div { div {1}, div {2} },
      div { div {3}, div {4} };
Код не вставишь
       :(
явный print
  отстой
запятые в топку
Да прибудут с
вами контексты
Контексты (context1.pl)


unless ( defined wantarray ) {
      # void
} elsif ( wantarray ) {
      # array
} else {
      # scalar
}
Контексты
sub div(&) {
  my $res = join '', shift->();
  unless ( defined wantarray ) {
     print „<div>$res</div>”;
  } else {
     return „<div>$res</div>”;
  }
}
Контексты (context1.pl)



div { div {1}; div {2} };

<div>1</div>
<div><div>2</div></div>
Буферизация
Бу-эфиры (buffers1.pl)

sub buffered {
  my $buf = '';
  local *STDOUT;
  open STDOUT, '>', $buf;
  return $buf . join('', shift->());
}
Бу-эфиры (buffers1.pl)

sub div(&) {
 my $res = buffered(shift);
 return „<div>$res</div>”
  if defined wantarray;
 print „<div>$res</div>”;
}
Бу-эфиры (buffers1.pl)

div {
 div{'menu'};
 my $some = 'some';
 div{$some},
 div{'tail'}
};
ЯХУ! :)
Грабли №3
Грабли №3


div {
 'some';
 my $some = 'some';
 div{$some}
};
Грабли №3



print 'some';
outs('some');
x {'some'}
{ my $x=...; 'some', div{$x} }
Установка
 функций
Установка функций

my @tags = qw(a b);
foreach my $t ( @tags ) {
   no strict 'refs';
   *{'main::'.$t} = sub (&) {
     ...
   };
}
Установка функций

sub import;
 Exporter;
  Symbol;
 И прочие
Прото-цепочки
Это не химия
И не биология
Это
(&;$)
Прото-цепочки


sub a(&;$) {
  print 'a ', context wantarray, "n"
}
sub b(&;$) {
  print 'b ', context wantarray, "n"
}
Прото-цепочки

a {} b {};

 b scalar
  a void
Промежуточное
 прдставление
Пром-представления
*{'main::'.$t} = sub (&;$) {
  my ($code, $next) = @_;
  unless ( defined wantarray ) {
     return _tag($t, $code, $next);
  } else {
     return bless sub {
        return _tag($t, $code, $next)
     }, 'MyTag';
  }
};
Пром-представления


package MyTag;
use overload '""' => sub {
  return buffered($_[0])
};
1;
Пром-представления

  a {'head'}
  b {'middle'}
   c {'tail'};
im_represent.pl
Экранирование
Экранирование

sub _escape {
  return unless defined $_[0];
  my $v = shift;
  $v = „$v”;
       „$v”;
  $v =~ s/.../.../g;
  return $v;
}
Экранирование

sub escape(@_) {
  return map
    blessed($_)
    && $_->isa('MyTag')
      ? $_ : _escape($_),
  @_;
}
Экранирование
sub buffered {
  ...
  return join '', $buf,
escape(@tail);
}
sub _tag {
  my ($tag, $code, $next) = @_;
  ...
  print join '', $res, escape $next;
}
Все работает
 escaping.pl
На закуску к экранам


sub outs(@) { print _escape(join '', @_) }

sub raw(@) { print join '', @_ }

# грабли №3
div { outs('some'); div {...} };
MyTD готов.
 Осталось
 только...
Недостающие части

объединить все примеры
запаковать все

sub template($$);
# template 'index' => run {};
sub show($@);
# show 'index', arg => $arg, ...;
Посмотреть

Template::Declare
Jifty::Dispatcher
Jifty::Param::Schema
Jifty::DBI::Schema
Object::Declare
B::*
ВСЕ
Вопросы?

Weitere ähnliche Inhalte

Was ist angesagt?

I tmozg js_school
I tmozg js_schoolI tmozg js_school
I tmozg js_school
ITmozg
 
Ubercart -nemnogo_primerov_iz_zhizni
Ubercart  -nemnogo_primerov_iz_zhizniUbercart  -nemnogo_primerov_iz_zhizni
Ubercart -nemnogo_primerov_iz_zhizni
drupalconf
 
Импорт данных с фреймворком Migrate. Владислав Богатырев.
Импорт данных с фреймворком Migrate. Владислав Богатырев.Импорт данных с фреймворком Migrate. Владислав Богатырев.
Импорт данных с фреймворком Migrate. Владислав Богатырев.
DrupalCampDN
 
Making Scalable JavaScript Application
Making Scalable JavaScript ApplicationMaking Scalable JavaScript Application
Making Scalable JavaScript Application
Mikhail Davydov
 
Entity. Anton Shubkin and Yaroslav Ponomarev
Entity. Anton Shubkin and Yaroslav PonomarevEntity. Anton Shubkin and Yaroslav Ponomarev
Entity. Anton Shubkin and Yaroslav Ponomarev
ADCI Solutions
 
I tmozg js_school_jquery
I tmozg js_school_jqueryI tmozg js_school_jquery
I tmozg js_school_jquery
ITmozg
 
Web осень 2013 лекция 4
Web осень 2013 лекция 4Web осень 2013 лекция 4
Web осень 2013 лекция 4
Technopark
 
Python
PythonPython
Python
pelid
 
Meet Magento Belarus debug Pavel Novitsky (rus)
Meet Magento Belarus debug Pavel Novitsky (rus)Meet Magento Belarus debug Pavel Novitsky (rus)
Meet Magento Belarus debug Pavel Novitsky (rus)
Pavel Novitsky
 

Was ist angesagt? (20)

Perl 5.10 и 5.12
Perl 5.10 и 5.12Perl 5.10 и 5.12
Perl 5.10 и 5.12
 
I tmozg js_school
I tmozg js_schoolI tmozg js_school
I tmozg js_school
 
Разработка на стероидах или как я перестал бояться и полюбил свою IDE
Разработка на стероидах или как я перестал бояться и полюбил свою IDEРазработка на стероидах или как я перестал бояться и полюбил свою IDE
Разработка на стероидах или как я перестал бояться и полюбил свою IDE
 
Не верь никому или разработка эффективных приложений (Как писать по настоящем...
Не верь никому или разработка эффективных приложений (Как писать по настоящем...Не верь никому или разработка эффективных приложений (Как писать по настоящем...
Не верь никому или разработка эффективных приложений (Как писать по настоящем...
 
Ubercart -nemnogo_primerov_iz_zhizni
Ubercart  -nemnogo_primerov_iz_zhizniUbercart  -nemnogo_primerov_iz_zhizni
Ubercart -nemnogo_primerov_iz_zhizni
 
Импорт данных с фреймворком Migrate. Владислав Богатырев.
Импорт данных с фреймворком Migrate. Владислав Богатырев.Импорт данных с фреймворком Migrate. Владислав Богатырев.
Импорт данных с фреймворком Migrate. Владислав Богатырев.
 
Making Scalable JavaScript Application
Making Scalable JavaScript ApplicationMaking Scalable JavaScript Application
Making Scalable JavaScript Application
 
Python dict: прошлое, настоящее, будущее
Python dict: прошлое, настоящее, будущееPython dict: прошлое, настоящее, будущее
Python dict: прошлое, настоящее, будущее
 
Render API.
Render API.Render API.
Render API.
 
PHP basic
PHP basicPHP basic
PHP basic
 
Perl: Symbol table
Perl: Symbol tablePerl: Symbol table
Perl: Symbol table
 
Entity. Anton Shubkin and Yaroslav Ponomarev
Entity. Anton Shubkin and Yaroslav PonomarevEntity. Anton Shubkin and Yaroslav Ponomarev
Entity. Anton Shubkin and Yaroslav Ponomarev
 
Пластилиновый код: как перестать кодить и начать жить
Пластилиновый код: как перестать кодить и начать житьПластилиновый код: как перестать кодить и начать жить
Пластилиновый код: как перестать кодить и начать жить
 
I tmozg js_school_jquery
I tmozg js_school_jqueryI tmozg js_school_jquery
I tmozg js_school_jquery
 
Avito / SPA Meetup 2
Avito / SPA Meetup 2Avito / SPA Meetup 2
Avito / SPA Meetup 2
 
Сергей Бережной "Клиентский JavaScript в БЭМ-терминах: от блока до библиотеки"
Сергей Бережной "Клиентский JavaScript в БЭМ-терминах: от блока до библиотеки"Сергей Бережной "Клиентский JavaScript в БЭМ-терминах: от блока до библиотеки"
Сергей Бережной "Клиентский JavaScript в БЭМ-терминах: от блока до библиотеки"
 
Web осень 2013 лекция 4
Web осень 2013 лекция 4Web осень 2013 лекция 4
Web осень 2013 лекция 4
 
Python
PythonPython
Python
 
Функциональные тесты на Perl
Функциональные тесты на PerlФункциональные тесты на Perl
Функциональные тесты на Perl
 
Meet Magento Belarus debug Pavel Novitsky (rus)
Meet Magento Belarus debug Pavel Novitsky (rus)Meet Magento Belarus debug Pavel Novitsky (rus)
Meet Magento Belarus debug Pavel Novitsky (rus)
 

Andere mochten auch (6)

Devel::PPAP
Devel::PPAPDevel::PPAP
Devel::PPAP
 
W200 Powerpoint
W200 PowerpointW200 Powerpoint
W200 Powerpoint
 
Ellies Enchanted Garden
Ellies  Enchanted  GardenEllies  Enchanted  Garden
Ellies Enchanted Garden
 
Social Media For Emergency Response Communications
Social Media For Emergency Response CommunicationsSocial Media For Emergency Response Communications
Social Media For Emergency Response Communications
 
Mtman
MtmanMtman
Mtman
 
Canvas Student Orientation at Stritch
Canvas Student Orientation at StritchCanvas Student Orientation at Stritch
Canvas Student Orientation at Stritch
 

Ähnlich wie DSLs в Perl

plwww (24.03) MEPHI (PHDays)
plwww (24.03) MEPHI (PHDays)plwww (24.03) MEPHI (PHDays)
plwww (24.03) MEPHI (PHDays)
ygoltsev
 
Юрий Гольцев - Сервис PLWWW
Юрий Гольцев - Сервис PLWWWЮрий Гольцев - Сервис PLWWW
Юрий Гольцев - Сервис PLWWW
Positive Hack Days
 
PHP Tricks
PHP TricksPHP Tricks
PHP Tricks
BlackFan
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)
ZFConf Conference
 
Symfony2. На чем можно сэкономить время при разработке?
Symfony2. На чем можно сэкономить время при разработке?Symfony2. На чем можно сэкономить время при разработке?
Symfony2. На чем можно сэкономить время при разработке?
Stepan Tanasiychuk
 
Разработка расширяемых приложений на Django
Разработка расширяемых приложений на DjangoРазработка расширяемых приложений на Django
Разработка расширяемых приложений на Django
MoscowDjango
 
Interactive git-diff
Interactive git-diffInteractive git-diff
Interactive git-diff
mvuets
 

Ähnlich wie DSLs в Perl (20)

Почему Mojolicious?
Почему Mojolicious?Почему Mojolicious?
Почему Mojolicious?
 
Mojolicious
MojoliciousMojolicious
Mojolicious
 
Yserver
YserverYserver
Yserver
 
plwww (24.03) MEPHI (PHDays)
plwww (24.03) MEPHI (PHDays)plwww (24.03) MEPHI (PHDays)
plwww (24.03) MEPHI (PHDays)
 
Юрий Гольцев - Сервис PLWWW
Юрий Гольцев - Сервис PLWWWЮрий Гольцев - Сервис PLWWW
Юрий Гольцев - Сервис PLWWW
 
Миша Рудрастых: Введение в HTTP API WordPress
Миша Рудрастых: Введение в HTTP API WordPressМиша Рудрастых: Введение в HTTP API WordPress
Миша Рудрастых: Введение в HTTP API WordPress
 
Перевод базы Caché из 8 бит в Unicode
Перевод базы Caché из 8 бит в UnicodeПеревод базы Caché из 8 бит в Unicode
Перевод базы Caché из 8 бит в Unicode
 
Интеграция Яндекс Сервер
Интеграция Яндекс СерверИнтеграция Яндекс Сервер
Интеграция Яндекс Сервер
 
Как очистить массив
Как очистить массивКак очистить массив
Как очистить массив
 
Caching on highload Drupal site - Alexander Shumenko
Caching on highload Drupal site - Alexander ShumenkoCaching on highload Drupal site - Alexander Shumenko
Caching on highload Drupal site - Alexander Shumenko
 
PHP Tricks
PHP TricksPHP Tricks
PHP Tricks
 
Enterprise Patterns in Magento
Enterprise Patterns in MagentoEnterprise Patterns in Magento
Enterprise Patterns in Magento
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 1)
 
Symfony2. На чем можно сэкономить время при разработке?
Symfony2. На чем можно сэкономить время при разработке?Symfony2. На чем можно сэкономить время при разработке?
Symfony2. На чем можно сэкономить время при разработке?
 
ITCrowd - Метапрограммирование
ITCrowd - МетапрограммированиеITCrowd - Метапрограммирование
ITCrowd - Метапрограммирование
 
Разработка расширяемых приложений на Django
Разработка расширяемых приложений на DjangoРазработка расширяемых приложений на Django
Разработка расширяемых приложений на Django
 
Magento code debugging
Magento code debuggingMagento code debugging
Magento code debugging
 
Present saint-per3-by-pavel-vlasov
Present saint-per3-by-pavel-vlasovPresent saint-per3-by-pavel-vlasov
Present saint-per3-by-pavel-vlasov
 
Interactive git-diff
Interactive git-diffInteractive git-diff
Interactive git-diff
 
msumobi2. Лекция 2
msumobi2. Лекция 2msumobi2. Лекция 2
msumobi2. Лекция 2
 

DSLs в Perl