Динамические возможности Perl Валерий Студенников despair [at] reg.ru 2010.

Презентация:



Advertisements
Похожие презентации
© Luxoft Training 2013 Annotations. © Luxoft Training 2013 Java reflection / RTTI // given the name of a class, get a "Class" object that // has all info.
Advertisements

1 © Luxoft Training 2012 Inner and anonymous classes.
1/27 Chapter 9: Template Functions And Template Classes.
Java Server Pages(JSP). JavaServer Pages (JSP) позволяют вам отделить динамическую часть ваших страниц от статического HTML. Вы, как обычно, пишете обычный.
Arrays Dr. Ramzi Saifan Slides adapted from Prof. Steven Roehrig.
Using Dreamweaver MX Slide 1 Window menu Manage Sites… Window menu Manage Sites… 2 2 Open Dreamweaver 1 1 Set up a website folder (1). Click New…
Test 14 Вопрос 1. class Main { public void method() { static class One { public One() { System.out.println("From one"); } } public static void main(String...
Inner Classes. 2 Simple Uses of Inner Classes Inner classes are classes defined within other classes The class that includes the inner class is called.
PL/SQL Пакеты. Определение Пакет – это объект схемы данных, объединяющий набор типов, объектов и подпрограмм PL/SQL.
Test 3 Вопрос 1. 01:package test; 02: public class Test { 03: public static void main(String [] args) { 04: Test test = new Test(); 05: System.out.println(test.toString());}
Test 4 Вопрос 1. public class TestOutput { public static void main(String[] args) throws IOException { PrintStream out = new PrintStream( new BufferedOutputStream(
Standard I/O and Pipes. Standard Input and Output Linux provides three I/O channels to Programs Standard input (STDIN) - keyboard by default Standard.
A class is just a collection of variables--often of different types--combined with a set of related functions. The variables in the class are referred.
PHP как язык программированияPHP как язык программирования.
Copyright 2003 CCNA 2 Chapter 14 Managing Cisco IOS Software By Your Name.
Structured Error Handling in the ABL Sarah Marshall QA Architect, OpenEdge Session 128.
Loader Design Options Linkage Editors Dynamic Linking Bootstrap Loaders.
1 A + B Операнд 1Операнд 2 Оператор Что такое выражение (expression) ? Что такое инструкция (statement) ? Операторы int max = (a > b) ? a : b;
Mock-объекты mock (англ.) – ложный, фиктивный, мнимый, фальшивый, поддельный.
1/30 Chapter 8: Dynamic Binding And Abstract classes.
Транксрипт:

Динамические возможности Perl Валерий Студенников despair [at] reg.ru 2010

Динамический язык? Динамический язык позволяет осуществлять синтаксический анализ и компиляцию «на лету», непосредственно на этапе выполнения. (c) Wikipedia Динамический язык позволяет менять код / структуру программы во время выполнения; Perl – динамический язык. В Perl «На лету» (уже после загрузки / компиляции приложения) можно делать ВСЁ.

Символические ссылки # ${ $ref $ref } %{ $ref } \&{ $ref } # no strict, should build & run ok my $fred ; $b = "fred" ; $a = $$b ; $c = ${"def"} ; $c ; $c = %{"def"} ; $c = *{"def"} ; $c = \&{"def"} ;

Как избежать предупреждений ${'XXX'} = 123; # Получаем: Can't use string ("XXX") as a SCALAR ref while "strict refs" in use at - line YYY. # Боремся так: { no strict 'refs'; # Здесь делаем грязные дела… } Can't use string ("XXX") as a SCALAR ref while "strict refs" in use at - line YYY. # Боремся так: { no strict 'refs'; # Здесь делаем грязные дела… }

Обращение к переменной по имени $var = = (1); %var = (1, 2); $name = 'var'; print %{$name}; print ${__PACKAGE__.'::'.$name}; print eval '$name';

Создание переменных на лету $varname = 'myname'; ${$varname} = 123; ${__PACKAGE__.'::'.$varname} = 123; eval \$$varname = 123;

Typeglobs *this = *that; local *Here::blue = \$There::green; $fh = *STDOUT; $fh = \*STDOUT; *dick = \$richard; *dick = *dick = \%richard;

Выполнение произвольного кода # Используется для отлова исключений: eval {}; # Выполнить произвольный код eval "print 123"; # eval не нужно злоупотреблять! Пример: создание функции на лету # Создаст функцию и сразу поместит в namespace eval 'sub sqr { $_[0] * $_[0] }'; print sqr( 2 );

Выполнение кода из файла # Загрузить и выполнить содержимое файла do $filename; # Эквивалент "do": eval `cat $filename` # Так можно сделать простейшие конфиги # Хотя это и не рекомендуется.... $config = ( dbname => 'test', username => 'test', pass => 'sdsfdf' );

perl -MData::Dumper -e 'print Dumper( \%INC )' $VAR1 = { 'warnings/register.pm' => '/usr/lib/perl5/5.10.0/warnings/register.pm', 'bytes.pm' => '/usr/lib/perl5/5.10.0/bytes.pm', 'XSLoader.pm' => '/usr/lib/perl5/5.10.0/i386-linux-thread-multi/XSLoader.pm',... 'Data/Dumper.pm' => '/usr/lib/perl5/5.10.0/i386-linux-thread-multi/Data/Dumper.pm' }; perl -MCGI -e 'print( join "\n", sort keys %INC );' CGI.pm CGI/Util.pm Carp.pm Exporter.pm... perl -e 'print join perl -MData::Dumper -e 'print Dumper( \%INC )' $VAR1 = { 'warnings/register.pm' => '/usr/lib/perl5/5.10.0/warnings/register.pm', 'bytes.pm' => '/usr/lib/perl5/5.10.0/bytes.pm', 'XSLoader.pm' => '/usr/lib/perl5/5.10.0/i386-linux-thread-multi/XSLoader.pm',... 'Data/Dumper.pm' => '/usr/lib/perl5/5.10.0/i386-linux-thread-multi/Data/Dumper.pm' }; perl -MCGI -e 'print( join "\n", sort keys %INC );' CGI.pm CGI/Util.pm Carp.pm Exporter.pm...

Подгрузка модулей на лету require $filename; # Безопасная одноразовая загрузка модулей sub use_once ($) { my ($module) my $module_file = $module.'.pm'; $module_file =~ s/::/\//xmsg; unless ($INC{$module_file}) { eval { require $module_file } or return; import $module; } return 1; }

Вызов функции / метода по имени $subname = 'sqr'; # Вызов функции по имени $subname->(2); &$subname( 2 ); *{$subname}->(2); # Вызов функции пакета __PACKAGE__->$subname(2); main->$subname(2); # Вызов метода по имени $object->$subname(2);

Вызов функции из неизвестного пакета $package = 'MyPackage'; # Имя функции известно заранее: $package->action(); # Имя функции заранее не известно: $subname = 'action'; ); # Первым аргументом будет передано название пакета! &{ $package. '::'. $subname );

Получить ссылку на функцию $packagename = 'MyPackage'; $subname = 'sqr'; # Из своего пакета: $ref = \&{$subname}; # Предпочтительнее $ref = *{$subname}; # Из чужого пакета $ref = \&{ $packagename. '::'. $subname }; $ref = *{ $packagename. '::'. $subname };

Вызов функции по ссылке my $ref; # Ссылка на функцию ); ); goto &$ref; # Будет задействован goto &$AUTOLOAD;

Запись функции в пространство имён $subname = 'alias'; $packagename = 'MyPackage'; # Записываем в namespace текущего пакета *{$subname} = \&sqr; alias( 4 ); # Записываем в namespace произвольного пакета *{"${packagename}::$subname"} = $coderef; $packagename->alias(2);

Способы переопределения функции # 1 package A; sub test { 1 }; package B; sub A::test { 2 }; print A::test(); # prints 2 # 2 *{"A::test"} = $coderef; # 3 package A; sub test { 1 }; package B; 1; package A; sub test { 2 }; package B; print A::test(); # prints 2

Просмотр содержимого namespace package A; = (1,2,3); sub two { 2 }; package main; print Dumper(\%{*{A::}}); # A:: typeglob # 'a' => *A::a, # 'two' => *A::two print Dumper( *{A::a}{ARRAY} ); # SCALAR | ARRAY | HASH | CODE | IO # PACKAGE | NAME

Замыкания sub outer_sub { $variable = shift; sub inner_sub { print $variable; }

Пример применения замыканий: accessors sub make_ro_accessor { my($class, $field) my $subref = sub { my $self = shift; return &{*{"${class}::get"}}($self, $field); }; *{"${class}::get_$field"} = $subref; } print $object->get_account_balance; # Вызов аналогичен $object->get('account_balance');

AUTOLOAD: пример 1 sub AUTOLOAD { our $AUTOLOAD; return "I see } print blarg(123); # prints «I see main::blarg(123)» sub AUTOLOAD { our $AUTOLOAD; return "I see } sub AUTOLOAD { our $AUTOLOAD; return "I see } print blarg(123); # sub AUTOLOAD { our $AUTOLOAD; return "I see } print blarg(123); #

AUTOLOAD: пример 2 sub AUTOLOAD { my $package = my $name = our $AUTOLOAD; *$AUTOLOAD = sub { print "I see }; goto &$AUTOLOAD; # Restart the new routine. } blarg(30); # prints: I see main::blarg(30) glarb(40); # prints: I see main::glarb(40) blarg(50); # prints: I see main::blarg(50)

overload use overload '+' => \&myadd, '-' => \&mysub; use Number::Fraction ':constants' my $f1 = '1/2'; print $f1 + 1/3; # prints '5/6'

Перезаписывание объектов чужого пакета package = 123; sub bar { 1234 }; package B; # Перезаписываем функции / переменные пакета package = 456; sub bar { 5678 }; # Теперь доступны перезаписанные версии package main; print A::bar();

caller кто нас вызвал? ($package, $filename, $line, $subroutine, $hasargs, $wantarray, $evaltext, $is_require, $hints, $bitmask, $hinthash) = caller($i); ($package, $filename, $line) = caller; # Можем получить аргументы вызывающих функций и фактически вручную получить полный backtrace package

Devel::Caller Devel::Caller - meatier versions of caller caller_cv($level) Возвращает coderef вызвающей функции caller_args($level) Возвращает аргументы вызывающей функции caller_vars( $level, $names ) Возвращает ссылки на переданные аргументы или имена (!) аргументов called_as_method($level) Была ли вызвана подпрограмма как метод?

Devel::Declare Определение новых ключевых слов / синтаксических конструкций # Например: method foo ($arg1, $arg2) {... } => sub foo { my ($self, $arg1, $arg2) }

PadWalker PadWalker - play with other peoples' lexical variables peek_my LEVEL peek_our LEVEL peek_sub SUB closed_over SUB set_closed_over SUB, HASH_REF var_name LEVEL, VAR_REF var_name SUB, VAR_REF

Где это может быть полезно? Выход в «четвёртое измерение»; Всевозможные хаки; Исправление поведения чужих модулей.

Пример :: Template Toolkit # # Compiled template generated by the Template Toolkit version 2.22 # I see main::blarg(123) Template::Document->new({ METADATA => { 'modtime' => ' ', 'name' => 'header.inc', }, BLOCK => sub { my $context = shift || die "template sub called without context\n"; my $stash = $context->stash; my $output = ''; my $_tt_error; eval { BLOCK: { #line 1 "/www/srs/templates/regru/header.inc" # MACRO $stash->set('marker', sub { my $_tt_params = $_[0] if ref($_[0]) eq 'HASH'; my $output = ''; my $stash = $context->localise($_tt_params); eval { $output.= ' ► '; }; $stash = $context->delocalise(); die if return $output; }); #line 2 "/www/srs/templates/regru/header.inc" # MACRO $stash->set('marker2', sub { my $_tt_params = $_[0] if ref($_[0]) eq 'HASH'; my $output = ''; my $stash = $context->localise($_tt_params); eval { $output.= ' '; }; $stash = $context->delocalise(); die if return $output; });...

Что почитать perlmod: typeglob: perldata ("Typeglobs and Filehandles"): Typeglobs and Filehandles