SlideShare a Scribd company logo
1 of 94
Download to read offline
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::*
ВСЕ
Вопросы?

More Related Content

What's hot

I tmozg js_school
I tmozg js_schoolI tmozg js_school
I tmozg js_schoolITmozg
 
Разработка на стероидах или как я перестал бояться и полюбил свою IDE
Разработка на стероидах или как я перестал бояться и полюбил свою IDEРазработка на стероидах или как я перестал бояться и полюбил свою IDE
Разработка на стероидах или как я перестал бояться и полюбил свою IDEMagento Dev
 
Не верь никому или разработка эффективных приложений (Как писать по настоящем...
Не верь никому или разработка эффективных приложений (Как писать по настоящем...Не верь никому или разработка эффективных приложений (Как писать по настоящем...
Не верь никому или разработка эффективных приложений (Как писать по настоящем...Moscow.pm
 
Ubercart -nemnogo_primerov_iz_zhizni
Ubercart  -nemnogo_primerov_iz_zhizniUbercart  -nemnogo_primerov_iz_zhizni
Ubercart -nemnogo_primerov_iz_zhiznidrupalconf
 
Импорт данных с фреймворком Migrate. Владислав Богатырев.
Импорт данных с фреймворком Migrate. Владислав Богатырев.Импорт данных с фреймворком Migrate. Владислав Богатырев.
Импорт данных с фреймворком Migrate. Владислав Богатырев.DrupalCampDN
 
Making Scalable JavaScript Application
Making Scalable JavaScript ApplicationMaking Scalable JavaScript Application
Making Scalable JavaScript ApplicationMikhail Davydov
 
Python dict: прошлое, настоящее, будущее
Python dict: прошлое, настоящее, будущееPython dict: прошлое, настоящее, будущее
Python dict: прошлое, настоящее, будущееdelimitry
 
PHP basic
PHP basicPHP basic
PHP basicNoveo
 
Entity. Anton Shubkin and Yaroslav Ponomarev
Entity. Anton Shubkin and Yaroslav PonomarevEntity. Anton Shubkin and Yaroslav Ponomarev
Entity. Anton Shubkin and Yaroslav PonomarevADCI Solutions
 
Пластилиновый код: как перестать кодить и начать жить
Пластилиновый код: как перестать кодить и начать житьПластилиновый код: как перестать кодить и начать жить
Пластилиновый код: как перестать кодить и начать житьMoscow.pm
 
I tmozg js_school_jquery
I tmozg js_school_jqueryI tmozg js_school_jquery
I tmozg js_school_jqueryITmozg
 
Сергей Бережной "Клиентский JavaScript в БЭМ-терминах: от блока до библиотеки"
Сергей Бережной "Клиентский JavaScript в БЭМ-терминах: от блока до библиотеки"Сергей Бережной "Клиентский JavaScript в БЭМ-терминах: от блока до библиотеки"
Сергей Бережной "Клиентский JavaScript в БЭМ-терминах: от блока до библиотеки"Yandex
 
Web осень 2013 лекция 4
Web осень 2013 лекция 4Web осень 2013 лекция 4
Web осень 2013 лекция 4Technopark
 
Python
PythonPython
Pythonpelid
 
Функциональные тесты на Perl
Функциональные тесты на PerlФункциональные тесты на Perl
Функциональные тесты на PerlIlya Zelenchuk
 
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
 

What's hot (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)
 

Viewers also liked

Ellies Enchanted Garden
Ellies  Enchanted  GardenEllies  Enchanted  Garden
Ellies Enchanted Gardenbimbionic
 
Social Media For Emergency Response Communications
Social Media For Emergency Response CommunicationsSocial Media For Emergency Response Communications
Social Media For Emergency Response CommunicationsBWEST Interactive
 
Canvas Student Orientation at Stritch
Canvas Student Orientation at StritchCanvas Student Orientation at Stritch
Canvas Student Orientation at StritchDavid Weinberg-Kinsey
 

Viewers also liked (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
 

Similar to 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
Юрий Гольцев - Сервис PLWWWPositive Hack Days
 
Миша Рудрастых: Введение в HTTP API WordPress
Миша Рудрастых: Введение в HTTP API WordPressМиша Рудрастых: Введение в HTTP API WordPress
Миша Рудрастых: Введение в HTTP API WordPressRuslan Begaliev
 
Перевод базы Caché из 8 бит в Unicode
Перевод базы Caché из 8 бит в UnicodeПеревод базы Caché из 8 бит в Unicode
Перевод базы Caché из 8 бит в UnicodeInterSystems
 
Интеграция Яндекс Сервер
Интеграция Яндекс СерверИнтеграция Яндекс Сервер
Интеграция Яндекс СерверPVasili
 
Как очистить массив
Как очистить массивКак очистить массив
Как очистить массивAndrew Shitov
 
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 ShumenkoDrupalCampDN
 
PHP Tricks
PHP TricksPHP Tricks
PHP TricksBlackFan
 
Enterprise Patterns in Magento
Enterprise Patterns in MagentoEnterprise Patterns in Magento
Enterprise Patterns in MagentoVrann Tulika
 
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
 
ITCrowd - Метапрограммирование
ITCrowd - МетапрограммированиеITCrowd - Метапрограммирование
ITCrowd - МетапрограммированиеITCrowd Almaty
 
Разработка расширяемых приложений на Django
Разработка расширяемых приложений на DjangoРазработка расширяемых приложений на Django
Разработка расширяемых приложений на DjangoMoscowDjango
 
Magento code debugging
Magento code debuggingMagento code debugging
Magento code debuggingaheadWorks
 
Present saint-per3-by-pavel-vlasov
Present saint-per3-by-pavel-vlasovPresent saint-per3-by-pavel-vlasov
Present saint-per3-by-pavel-vlasovPavel Vlasov
 
Interactive git-diff
Interactive git-diffInteractive git-diff
Interactive git-diffmvuets
 

Similar to 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