Вы находитесь на странице: 1из 81

Pragmatic Perl

pragmaticperl.com
3. 2013

hp://pragmaticperl.com.
editor@pragmaticperl.com.
html-.
pragmaticperl.com/subscribe.
: , Jerey alhammer (thalje),
(crux),
: (vti)
: 2013-05-01 11:03
Pragmatic Perl

. . . . . . . . . . . . . . . . . . . . . . . . .

, ORM- . . . . . . . . . . . . .

Pinto CPAN . . . . . . . . . . 12

Perl XS . . . . . . . . . . . . . . . . . . . . . . 24

web- PSGI/Plack.
2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

CPAN 2013 . . . . . . . . . . . . . . . . 61

Sawyer X . . . . . . . . . . . . . . . . . . . . 65

Perl iz . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74

Perl- . . . . . . . . . . . . . . . . . . . . . . . . . 77

1.
!
Jerey alhammer,
Perl- Perl::Critic. Pinto,
CPAN-. , Je
. Pinto , !
. ,
.
YAPC::Europe 2013 .
. !
.
, , .
.

,
ORM-

2. ,

ORM-
ORM-, .
, . ? , , ,
(, Test::Tutorial). ,
, ,
, . , , ORM-.
, ,
.
Rose::DB::Object.


, ORM-, ,
. , ,
ORM- , .
Active Record (Rose::DB::Object
DBIx::Class ),
.
ORM-

,
ORM-
ORM , . API, ,
,
, , ,
. , , , .
, .
Mock-.
?
:



, ,
.

-
. .
,
,
ORM- . :

1
,
, . :
1

package Language;

,
ORM-
2
3

use base qw(Rose::DB::Object);

4
5
6
7
8
9
10
11
12

__PACKAGE__>meta>setup(
table
=> languages,
columns => [
language_id => { type => varchar, length => 3,
not_null => 1 },
name
=> { type => varchar, length => 64,
not_null => 1 },
],
primary_key_columns => [ language_id ],
);

, ,
,
. ,
, :
1. , , , .
2. , , ORM-,
.
, , .
.
, ,
. Rose::DB::Object
Rose::DB::Object::Loader, DBIx::Class DBIx::Class::
Schema::Loader.

2
(Dependency
Injection), .
4

,
ORM-
. , .
1

. ,
,
. :
1

package TAX;

2
3

use base qw(Rose::DB::Object);

4
5
6
7
8
9
10
11
12

__PACKAGE__>meta>setup(
table
=> taxes,
columns => [
tax_id => { type => varchar, length
=> 16,
not_null => 1 },
rate
=> { type => integer, not_null => 1 }
],
primary_key_columns => [ tax_id ],
);

13
14

sub calculate_tax_amount

{ ... }

.
calculate_tax_amount.
:
1
2

my $tax
= Tax>new( tax_id => 'VAT_20' )>load();
my $tax_amount = $tax>calculate_tax_amount( 102.51 );

:
1. .
2. .
3. calculate_tax_amount
.

,
ORM-
.
1
2
3

my $tax_obj = Tax>new( rate => 20 );


is( $tax_obj>calculate_tax_amount( 123.01 ), 20.50 );
is( $tax_obj>calculate_tax_amount( 456.00 ), 76.00 );

, .
2
,
, . .
:
1
2
3
4
5
6
7

my $doc = FinancialDoc>new(
lines => [
{amount => 102.22},
{amount => 103.27}
],
date => "20101010"
);

8
9
10

$doc>build();
my $amount = $doc>tax_amount();

$doc>build , 2010 ,


tax_amount. .
,

FinancialDoc . tax_object ( ORM ) .
1
2
3

my $doc = FinancialDoc>new(
lines => [
{amount => 102.22},

,
ORM-
4
5
6
7
8
9

{amount => 103.27}


],
date => "20101010",
tax_object => Tax>new( rate => 20 )
);
$doc>build();

10
11

is( $doc>tax_amount(), 41.01 );

,

, , , . ,
.
:
1. DBI Mock,
.
2. .
? ,
, . ,
, , , , , , , , .
,
, , . , , , . , .
,
.
:
7

,
ORM-
3

. ,
? :
1. .
,
. ,
,
.
2. , , SQLite.
. , . , ,
.
3. .
, .
:
1

use Test::More;

2
3
4

my $db = Rose::DB>new_or_cached();
$db>begin_work();

5
6

init_test_data();

7
8

do_testing();

9
10

$db>rollback();

:
8

,
ORM-
1. .
2. . .
3. ,
.
4. .
, ,
. MySQL (InnoDB)
.
,
.
? , .
:
1. .
2. .
3.
.
,
.
:
1
2

use Test::More;
use Test::Project;

3
4

my $t = Test::Project>new();

5
6
7

$t>object_factory>buy_material_from_partner({price =>
1200});
$t>object_factory>buy_service_from_partner({price =>
1200});

,
ORM-
8
9
10
11
12
13

$t>iterate_test_data(
"report_a",
sub {
my ($report_params, $expected_output) = @_;
my $report = Project::Report::A>new(%
$report_params);

14
15

$t>test_report($report, $expected_output);

16
17

}
);

Test::Project, . ,
.
, , Test::Project:
1

package Test::Project;

2
3

use Moo;

4
5
6
7
8
9
10

has 'object_factory' => (


is
=> 'lazy',
default => sub {
return Test::ProjectObjectFactory>new();
}
);

11
12
13
14

has 'db' => (


is
=> 'lazy',
default => sub {

15
16

# Switch database
Project::DB>default_domain('test');
return Project::DB>new_or_cached();

17
18
19
20

}
);

21
22
23

sub BUILD {
my $self = shift;

24
25
26

die "ALREADY IN TRANSACTION" if $self>db>


in_transaction();
$self>db>begin_work();

27
28

return $self;

10

,
ORM-
29

30
31
32
33
34

sub DEMOLISH {
my $self = shift;
$self>db>rollback();
}

35
36

1;

, WebbyLab

11

Pinto CPAN

3. Pinto CPAN
Pinto CPAN-.
( 80%) . ! hp://tinyurl.com/gopinto
Perl ,
CPAN. .
, ,
.
CPAN, , . CPAN-
, CPAN.
CPAN-, CPAN::Mini CPAN::Site. .
CPAN.
. Pinto .
Pinto -

CPAN-. , Perl-. CPAN


Pinto .

Pinto
Pinto CPAN
, cpan cpanm . Pinto

, . , 12

Pinto CPAN
,
. Pinto :
1
2

curl L http://getpinto.stratopan.com | bash


source ~/opt/local/pinto/etc/bashrc

Pinto ~/opt/local/pinto, PATH MANPATH. , Pinto , Pinto.

Pinto
, ,
:
1
2
3

pinto commands
# Show a list of available
commands
pinto help <COMMAND>
# Show a summary of options and
arguments for <COMMAND>
pinto manual <COMMAND>
# Show the complete manual for
<COMMAND>

Pinto ,

. :
1
2
3
4

man Pinto::Manual::Introduction
conecpts
man Pinto::Manual::Installing
installing Pinto
man Pinto::Manual::Tutorial
Pinto
man Pinto::Manual::QuickStart
commands

13

# Explains basic Pinto


# Suggestions for
# A narrative guide to
# A summary of common

Pinto CPAN


Pinto init:
1

pinto r ~/repo init

~/repo. , . ,
.
r ( root) .
pinto. ,
PINTO_REPOSITORY_ROOT r.


, , .
, ,
list:
1

pinto r ~/repo list

,
. list .

CPAN-
MyApp, My::App URI. URI pull:
1

pinto r ~/repo pull URI

,
. 14

Pinto CPAN
, . .
, .
Pinto- URI. ,
. list
:
1

pinto r ~/repo list

, :
1
2
3
4

rf URI
rf URI::Escape
rf URI::Heuristic
...

1.60
3.31
4.20

GAAS/URI1.60.tar.gz
GAAS/URI1.60.tar.gz
GAAS/URI1.60.tar.gz

, URI ,
, .


MyApp ,
. (, ExtUtils::MakeMaker, Module::Build, Module::Install ..)
MyApp1.0.tar.gz. add:
1

$> pinto r ~/repo add path/to/MyApp1.0.tar.gz

, . , , My::App,
, .
1
2
3
4
5

rl
rf
rf
rf
...

My::App
URI
URI::Escape
URI::Heuristic

1.0
1.60
3.31
4.20

JEFF/MyApp1.0.tar.gz
GAAS/URI1.60.tar.gz
GAAS/URI1.60.tar.gz
GAAS/URI1.60.tar.gz

15

Pinto CPAN


Pinto- ,
. Pinto- CPAN-, cpanm Perl. , , Pinto
-:
1

cpanm mirror file://$HOME/repo mirroronly My::App

My::App, Pinto-.
, CPAN.
cpanm mirroronly ,
cpanm CPAN ,
. , , -
META. ,
pull
.


My
App URI CPAN 1.62.
,
. ,
pull. , URI
, ,
:
1

pinto r ~/repo pull URI~1.62

,
URI (, , ):
16

Pinto CPAN
1
2
3
4
5

rl
rf
rf
rf
...

My::App
URI
URI::Escape
URI::Heuristic

1.0
1.62
3.38
4.20

JEFF/MyApp1.0.tar.gz
GAAS/URI1.62.tar.gz
GAAS/URI1.62.tar.gz
GAAS/URI1.62.tar.gz

URI - , .
My::App 1.62.



. URI
, .
.
,
. .
CPAN- , , .
. Pinto .
. .
, perl5.8
perl5.16.
.
, .
.
, .
. , master .
17

Pinto CPAN
, . , master
.


, 1.60 URI,
1.62, . , .
, ,
master. ,
copy:
1

pinto r ~/repo copy master uri_upgrade

uri_upgrade. , list stack:


1

pinto r ~/repo list stack uri_upgrade

master:
1
2
3

rl My::App
rf URI
...

1.0
1.60

JEFF/MyApp1.0.tar.gz
GAAS/URI1.60.tar.gz


, URI.
, pull. Pinto
uri_upgrade:
1

pinto r ~/repo pull stack uri_upgrade URI~1.62

master uri_upgrade,
diff:
18

Pinto CPAN
1

pinto r ~/repo diff master uri_upgrade

2
3

+rf
4 +rf
5 +rf
6 ...
7 rf
8 rf
9 rf

URI
URI::Escape
URI::Heuristic

1.62 GAAS/URI1.62.tar.gz
3.31 GAAS/URI1.62.tar.gz
4.20 GAAS/URI1.62.tar.gz

URI
URI::Escape
URI::Heuristic

1.60 GAAS/URI1.60.tar.gz
3.31 GAAS/URI1.60.tar.gz
4.20 GAAS/URI1.60.tar.gz

diff(1). ,
+, , , .
, URI1.60 URI1.62.


uri_upgrade,
, cpanm . , :
1

cpanm mirror file://$HOME/repo/stacks/uri_upgrade


mirroronly My::App

, URI
1.62 master, pull.
master ,
:
1

pinto r ~/repo pull URI~1.62



. , ? MyApp, , ,
2.0 URI master.
19

Pinto CPAN
, URI MyApp , . , URI, , MyApp. , ,
URI. .


,
. ( ) . pin ( . . .):
1

pinto r ~/repo pin URI

master, :
1
2
3
4
5

...
rl My::App
rf! URI
rf! URI::Escape
...

1.0
1.60
3.31

JEFF/MyApp1.0.tar.gz
GAAS/URI1.60.tar.gz
GAAS/URI1.60.tar.gz

! , .
- URI ,
URI, Pinto
. ,
URI1.60,
( , ).


, , MyApp
URI .
, URI ,
unpin:
20

Pinto CPAN
1

pinto r ~/repo unpin URI

URI
. , .

. , prod, .
dev, . , dev prod.
dev. , prod,
, .


, CPAN- ,
(
).
CPAN-.
URI URI1.60_PATCHED.tar.gz. add:
1

pinto r ~/repo add path/to/URI1.60_PATCHED.tar.gz

,
, CPAN
21

Pinto CPAN
,
.
1

pinto r ~/repo pin URI

URI 1.62, , .
, copy. trial.
1

pinto r ~/repo copy master trial

URI trial :
1

pinto r ~/repo unpin stack trial URI

URI My::App
:
1
2

pinto r ~/repo pull stack trial URI~1.62


cpanm mirror file://$HOME/repo/stacks/trial mirror
only My::App

, master URI.
1
2

pinto r ~/repo unpin URI


pinto r ~/repo pull URI~1.62


, , , ,
, . log:
1

pinto r ~/repo log

:
1
2
3

revision 4a62d7ce245c45d489f8987080a90112
Date: Mar 15, 2013 1:58:05 PM
User: jeff

22

Pinto CPAN
4
5

Pin GAAS/URI1.59.tar.gz

6
7

Pinning URI because it is not causes our foo.t


script to fail

8
9
10
11

revision 4a62d7ce245c45d489f8987080a90112
Date: Mar 15, 2013 1:58:05 PM
User: jeff

12
13

Pull GAAS/URI1.59.tar.gz

14
15

URI is required for HTTP support in our application

16
17

...

. SHA-1 git.
[NB: ,
].


Pinto- .
.
, , , .

.
Jerey alhammer

23

Perl XS

4. Perl XS
, Perl- XS . , XS , , ,
, , ,
. , Perl XS ,
.

XS?
XS eXternal Subroutine ( ), ,
, C ( C++)
Perl-. XS Perl-
C-,

.
XSUB.
XS ,
(bindings) C-
Perl. , Gtk3
C- libgtk3.
XS , Perl
, C.
, , Math::FFT .
24

Perl XS
XS
. ,
Socket::Netlink
PF_NETLINK Linux.
XS Perl (XS- ) -
,
C/C++ (XS-). , ,
Perl
/++ XS, , ,
Swig XS,
Perl API.
, XS
. XS,
xsubpp, C-,
Perl API.
(typemaps)
Perl. ,
XS C-,
C-
.
XS , . XS ,
Perl API Perl, , XS- Perl .

Perl
Perl C, API Perl
C. ,
Perl, API-
,
Perl.
25

Perl XS
SV , Perl.

, ( :
, ,
) , , . , ,
, ( ).
AV , HV , CV , GV
, SV,
.
. , C, Perl
.
: IV
long, UV unsigned long, NV double, PV char *
. ,
,
,
API /.

Perl API
perlapi ( ) . Perl
API - ,
Perl, C API : , .
Perl API
API .
Perl - . ,
, .
,
, 26

Perl XS

Perl.
,
, ,
,
.
, :
SV* newSV(const STRLEN len) len+1 ( 1 -);
AV* newAV() ;
HV* newHV() .
, : new +
( ). , ( ), :
1
2
3

SV* newSViv(IV);
SV* newSVuv(UV);
SV* newSVnv(double);

, , , : iv , uv , nv ..
( ), , :
1
2
3
4
5

IV
UV
NV
char*
char*

SvIV(SV* sv)
SvUV(SV* sv)
SvNV(SV* sv)
SvPV(SV* sv, STRLEN len)
SvPV_nolen(SV* sv)

27

Perl XS
(Sv, Av)
(IV, NV) , . ,
:
int AvFILL(AV* av) ;
HV* CvSTASH(CV* cv) (- ).
,
:
void av_clear(AV *av) ;
AV* get_av(const char *name, I32 flags) ;
CV* get_cvn_flags(const char* name, STRLEN len, I32
flags) Perl-.
: av, cv ,
.
,
, ,
cvn, pvf, pvs. , n (.. , STRLEN), f
(sprintf), s (
const char*). :
void sv_catpv(SV *const sv, const char* ptr) sv;

28

Perl XS
void sv_catpvn(SV *dsv, const char *sstr, STRLEN len)

;
void sv_catpvs(SV* sv, const char* s) ,
sv_catpvn ();
void sv_catpvf(SV *const sv, const char *const pat,
...) sprintf(),
sv.
Perl API PL_, : PL_sv_undef undef, PL_na ,
.

XS-
xs, . xs- :
1
2
3

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

4
5

MODULE = MyModule

PACKAGE = MyModule

. , MODULE =, C-.
, MODULE =, , , xs-.
xsubpp POD-,
1-, 2- ,
,
.
Perl, 29

Perl XS
. ,
C, . MODULE
,
Perl- , (bootstrap) , PACKAGE
,
. xs- MODULE PACKAGE
,
.
, .
, hello,world! XS. , h2xs,

.
1
2
3
4
5
6
7
8

$ h2xs b 5.8.9 A n Hello::World usexsloader skip


ppport
Writing HelloWorld/lib/Hello/World.pm
Writing HelloWorld/World.xs
Writing HelloWorld/Makefile.PL
Writing HelloWorld/README
Writing HelloWorld/t/HelloWorld.t
Writing HelloWorld/Changes
Writing HelloWorld/MANIFEST

:
b Perl,
;
A AUTOLOAD;
usexsloader DynaLoader XSLoader;
skipppport
Perl API.
lib/Hello/World.pm:

30

Perl XS
1

package Hello::World;

2
3
4
5

use 5.008009;
use strict;
use warnings;

6
7

require Exporter;

8
9

our @ISA = qw(Exporter);

10
11
12

our %EXPORT_TAGS = ( 'all' => [ qw(


) ] );

13
14

our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );

15
16
17

our @EXPORT = qw(


);

18
19

our $VERSION = '0.01';

20
21
22

require XSLoader;
XSLoader::load('Hello::World', $VERSION);

23
24

1;

Hello::World.
: Exporter,
, XSLoader.
@EXPORT
, . @EXPORT_OK ,
, . ,
XS- . Perl, XS.
Makefile.PL:
1
2
3
4
5

use 5.008009;
use ExtUtils::MakeMaker;
WriteMakefile(
NAME
=> 'Hello::World',
VERSION_FROM
=> 'lib/Hello/World.pm',

31

Perl XS
6

PREREQ_PM
=> {},
($] >= 5.005 ?
## Add these new keywords
supported since 5.005
(ABSTRACT_FROM => 'lib/Hello/World.pm', # retrieve
abstract from module
AUTHOR
=> 'Vladimir Lettiev <crux@cpan.org
>') : ()),
LIBS
=> [''], # e.g., 'lm'
DEFINE
=> '', # e.g., 'DHAVE_SOMETHING'
# Insert I. if you add *.h files later:
INC
=> '', # e.g., 'I/usr/include/
other'
# Uncomment this if you add C files to link with
later:
# OBJECT
=> '$(O_FILES)', # link all the C
files too

7
8
9
10
11
12
13
14
15
16

);

XS- ,
xs. INC, , LIBS ,
, OBJECT
C- ,
.
Module::Install, Makefile
.PL :
1

use inc::Module::Install;

2
3
4
5

perl_version '5.008009';
name
'HelloWorld';
all_from
'lib/Hello/World.pm';

6
7

WriteAll;

XS- , Module::Install::XSUtil.
World.xs. , .
1
2

#include "EXTERN.h"
#include "perl.h"

32

Perl XS
3

#include "XSUB.h"

4
5

MODULE = Hello::World

PACKAGE = Hello::World

6
7
8
9
10

void
greeting()
CODE:
printf("Hello World!\n");

greeting(),
Hello World! . XSUB : void. ( ,
, ). XS. CODE ( ) , - .
:
1

$ perl Makefile.PL
...
3 $ make
4 cp lib/Hello/World.pm blib/lib/Hello/World.pm
5 /usr/bin/perl5.16.3 "Iinc" /usr/share/perl5/ExtUtils/
xsubpp typemap
6 /usr/share/perl5/ExtUtils/typemap
World.xs > World.xsc
&& mv World.xsc
7 World.c
8 Please specify prototyping behavior for World.xs (see
perlxs manual)
9 gcc c
D_REENTRANT D_GNU_SOURCE fnostrictaliasing
pipe
10 fstackprotector I/usr/local/include
D_LARGEFILE_SOURCE
11 D_FILE_OFFSET_BITS=64 pipe Wall g O2
DVERSION=\"
0.01\"
12 DXS_VERSION=\"0.01\" fPIC "I/usr/lib64/perl5/CORE"
World.c
13 Running Mkbootstrap for Hello::World ()
14 chmod 644 World.bs
15 rm f blib/arch/auto/Hello/World/World.so
16 gcc shared pipe Wall g O2 L/usr/local/lib fstack
protector World.o
17 o blib/arch/auto/Hello/World/World.so
\
18
\
19 L/usr/lib64/perl5/CORE lperl lpthread
2

33

Perl XS
20
21
22

chmod 755 blib/arch/auto/Hello/World/World.so


cp World.bs blib/arch/auto/Hello/World/World.bs
chmod 644 blib/arch/auto/Hello/World/World.bs

make. Perl blib. xsubpp, World


.xs World.xsc World.c. , xsubpp ,
( Perl), . C- gcc, . ,
perl ( perl V).
World.so World.bs blib/arch/auto/Hello/World.
- Perl-,
.
, , , .
:
1
2

$ perl Iblib/lib Iblib/arch MHello::World e 'Hello::


World::greeting()'
Hello World!

I , perl , M , e , greeting().
.
: C-
.
:
1
2
3

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

4
5
6
7

void greeting() {
printf("Hello World!\n");
}

34

Perl XS
9

MODULE = Hello::World

PACKAGE = Hello::World

10
11
12

void
greeting()

greeting() 1- XS-,
C-. -
! , , CODE .
xsubpp
C-, .
, , ,
- . , greeting
() xs #include . , .

XSUB
XS
perlxs.
XSUB-.
XS- Readonly::XS (
):
1
2
3

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

4
5

#include "ppport.h"

6
7

MODULE = Readonly::XS

PACKAGE = Readonly::XS

8
9
10
11
12

int
is_sv_readonly(sv)
SV *sv
PROTOTYPE: $

35

Perl XS
13
14
15
16

CODE:
RETVAL = SvREADONLY(sv);
OUTPUT:
RETVAL

? -, is_sv_readonly() int. , sv*, SV.


. PROTOTYPE,
Perl- $
. CODE , RETVAL
Perl API SvREADONLY(),
SVf_READONLY sv, ..
.
RETVAL , ,
. Perl-
. XS ST(x), x ,
. 0, ST(0). xsubpp RETVAL
ST(0),
.
OUTPUT xsubpp,
, XSUB Perl-.
xsubpp , RETVAL.
, ,
:
1
2
3
4
5
6

void
is_sv_readonly(sv)
SV *sv
PROTOTYPE: $
PPCODE:
PUSHs(sv_2mortal(newSViv(SvREADONLY(sv))));

36

Perl XS
CODE PPCODE,
xsubpp, . PPCODE :
SvREADONLY(sv) sv;
newSViv , ;
sv_2mortal ,
.. XSUB,
,
;
PUSHs (
).
.
.

Typemap
, , s_sv_readonly() int void. xsubpp Perl C . Perl
int, , int
, . , , C- Perl-
C-. , , typemap. xsubpp
C- Perl .
typemap : TYPEMAP, INPUT OUTPUT. , 37

Perl XS
- C- , XS-. INPUT , Perl C-. OUTPUT , C Perl .
, typemap int:
1
2
3
4
5
6
7

int
T_IV
INPUT
T_IV
$var = ($type)SvIV($arg)
OUTPUT
T_IV
sv_setiv($arg, (IV)$var);

, int XS- T_IV. INPUT XS- T_IV . xsubpp


:
$var , $type C, $arg . OUTPUT C- Perl-.
, INPUT OUTPUT Perl-, , eval,
, . . ,
Perl-. ,
typemap GTK:
1
2
3
4

T_GtkPTROBJOrNULL
$var = SvTRUE($arg)
? Cast$type(SvGtkObjectRef($arg, \"" . ($foo=
$ntype,$foo=~s/_OrNULL//,$foo). "\"))
: 0

, Perl-, _OrNULL . 38

Perl XS
,
.
, , .
XSUB,
:
1
2
3
4
5
6
7
8

double
avg(x,y)
int x
int y
CODE:
RETVAL = (double) (x+y)/2;
OUTPUT:
RETVAL

make xsubpp C, :
1

dVAR; dXSARGS;
if (items != 2)
croak_xs_usage(cv, "x, y");
{
int x = (int)SvIV(ST(0));
int y = (int)SvIV(ST(1));
double RETVAL;
dXSTARG;
RETVAL = (double) (x+y)/2;
XSprePUSH; PUSHn((double)RETVAL);
}
XSRETURN(1);

3
4
5
6
7
8
9
10
11
12
13
14

6- 7- int , typemap INPUT. RETVAL double , OUTPUT typemap :


1
2

T_DOUBLE
sv_setnv($arg, (double)$var);

xsubpp ,
PUSHn.
39

Perl XS
- , typemap. xsubpp
typemap
.

ppport.h
ppport.h.
Readonly::XS
ppport.h:
1

#include "ppport.h"

Devel::
PPPort , API- Perl
Perl.
. Perl 5.003 5.11.5.
C. Perl-, POD.
XS-
Perl
.
:
1

$ perl ppport.h
2 Scanning XS.xs...
3 Doesn't seem to need ppport.h.
4 XS.xs
20120831 22:24:26.000000000 +0400
5 +++ XS.xs.patched
20130416 00:01:57.386431309
+0400
6 @@ 2,7 +2,6 @@
7 #include "perl.h"
8 #include "XSUB.h"
9
10

#include "ppport.h"

11

40

Perl XS
12
13

MODULE = Readonly::XS

PACKAGE = Readonly::XS

POD :
1

$ perldoc ppport.h

:
1

$ perl MDevel::PPPort e 'Devel::PPPort::WriteFile();'

h2xs,
skipppport.


minstr() List::Util XS-
:
1
2

#define SLU_CMP_LARGER
1
#define SLU_CMP_SMALLER 1

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

void
minstr(...)
PROTOTYPE: @
ALIAS:
minstr = SLU_CMP_LARGER
maxstr = SLU_CMP_SMALLER
CODE:
{
SV *left;
int index;
if(!items) {
XSRETURN_UNDEF;
}
left = ST(0);
for(index = 1 ; index < items ; index++) {
SV *right = ST(index);
if(sv_cmp(left, right) == ix)
left = right;
}
ST(0) = left;

41

Perl XS
24
25

XSRETURN(1);
}

minstr() . 5- , ,
xsubpp,
.
items, , . 14 ,
. , XSRETURN_UNDEF,
&PL_sv_undef (undef).

,
ST(index).
ST(0). XSRETURN(1) XSUB

.
RETVAL.
, ALIAS.

, Perl: minstr() maxstr(). ix, , ALIAS. .. minstr
() ix SLU_CMP_LARGER,
maxstr() ix SLU_CMP_SMALLER.
.

(bindings) C-
(bindings) Perl-.

CPAN, .
, XML::LibXML, Gtk3, SDL ..
42

Perl XS

My::Libm, C libm.
:
1

$ h2xs b 5.8.9 A n My::Libm usexsloader skip


ppport

Libm.xs : ceil(), floor() pow(). , <math.h> . :


1
2
3

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

4
5

#include <math.h>

6
7

MODULE = My::Libm

PACKAGE = My::Libm

8
9
10
11
12

double
ceil(x)
double x
PROTOTYPE: $

13
14
15
16
17

double
floor(x)
double x
PROTOTYPE: $

18
19
20
21
22
23

double
pow(x, y)
double x
double y
PROTOTYPE: $$

libm, Makefile.PL LIBS


lm:
1
2
3
4
5

use 5.008009;
use ExtUtils::MakeMaker;
WriteMakefile(
NAME
=> 'My::Libm',
VERSION_FROM
=> 'lib/My/Libm.pm',

43

Perl XS
6

PREREQ_PM
=> {},
($] >= 5.005 ?
## Add these new keywords
supported since 5.00
(ABSTRACT_FROM => 'lib/My/Libm.pm',
AUTHOR
=> 'Vladimir Lettiev <crux@cpan.org
>') : ()),
LIBS
=> ['lm'],
INC
=> '',

7
8
9
10
11
12

);

math.h (/usr/include) IN .
lib/My/Libm.pm ,
:
1
2
3
4
5

...
our @EXPORT = qw(
ceil floor pow
);
...

, math.h (
glibc) :
1
2

$ perl Makefile.PL
$ make

( ),
t/MyLibm.t:
1
2

use strict;
use warnings;

3
4
5

use Test::More;
BEGIN { use_ok('My::Libm') };

6
7
8
9

is floor(1.9), 1, "floor()";
is ceil(1.9), 2, "ceil()";
is pow(2,3), 8, "pow()";

10
11

done_testing();

prove:
1

$ prove b v

44

Perl XS
2
3
4
5
6
7
8
9
10
11

t/MyLibm.t ..
ok 1 use My::Libm;
ok 2 floor()
ok 3 ceil()
ok 4 pow()
1..4
ok
All tests successful.
Files=1, Tests=4, 0 wallclock secs ( 0.05 usr
+ 0.05 cusr 0.00 csys = 0.10 CPU)
Result: PASS

0.00 sys

. make dist
CPAN. ,
, .


:
perlguts Perl;
perlapi API Perl;
perlxs XS;
perlxstut
XS;
perlapio PerlIO XS.
Google ,
, .
Perl.
!

45

web- PSGI/Plack. 2.

5. web-
PSGI/Pla. 2.
PSGI/Plack.
Plack::Builder, Plack::Middleware.
PSGI, , . Plack PSGI,
API, ,
PSGI .
:
Plack::Builder .
Plack::Middleware .
- Starman, preforking
( ).

Pla::Builder
Plack::Builder. . Plack::Builder Plack::Middleware , .
, ,
.
Plack::Builder :
1

builder {

46

web- PSGI/Plack. 2.
2
3

mount '/foo' => builder { $bar };


}

, /foo PSGI- ($bar). , builder


, :
Can't use string ("stupid string")as a subroutine ref while
"strict refs" in use at /usr/local/share/perl/5.14.2/Plack
/App/URLMap.pm line 71.

, :
1
2
3
4
5
6
7

builder {
mount '/foo' => builder {
mount '/bar' => builder { $bar; };
mount '/baz' => builder { $baz; };
mount '/'
=> builder { $foo; };
};
};

, /foo $foo, /foo/bar $bar,


/foo/baz $baz .
, :
1
2
3
4
5

builder {
mount '/foo/bar' => builder { $bar };
mount '/foo/baz' => builder { $baz };
mount '/foo/'
=> builder { $foo };
};

, . Plack::Builder - , . Plack::Builder
- :
1
2
3

my $builder = Plack::Builder>new;
$builder>mount('/foo' => $foo_app);
$builder>mount('/'
=> $root_app);

47

web- PSGI/Plack. 2.
4

$builder>to_app;

:
1
2
3
4

builder {
mount '/foo' => builder { $app; };
mount '/'
=> builder { $app2; };
};

.
Plack::Builder
Plack::Middleware.

Pla::Middleware
Plack::Middleware ,
CPAN, PSGI-.

? API.
, :
1
2

my $api_app = sub {
my $env
= shift;

3
4

my $req = Plack::Request>new($env);
my $res = $req>new_response(200);

5
6
7

my $params = $req>parameters();
if ($params>{string} && $params>{string} eq 'data')
{
$res>body('ok');
}
else {
$res>body('not ok');
}

8
9
10
11
12
13
14
15
16

return $res>finalize();
};

17
18
19
20

my $main_app = builder {
mount "/" => builder { $api_app };
}

48

web- PSGI/Plack. 2.
, ,
, POST.
:
1
2

my $api_app = sub {
my $env = shift;

3
4

my $req = Plack::Request>new($env);
my $res = $req>new_response(200);

5
6
7

my $params = $req>parameters();
if ($req>method() ne 'POST') {
$res>status(403);
$res>body('Method not allowed');
return $res>finalize();
}

8
9
10
11
12
13
14

if ($params>{string} && $params>{string} eq 'data')


{
$res>body('ok');
}
else {
$res>body('not ok');
}

15
16
17
18
19
20
21
22

return $res>finalize();
};

4 , . , ,
POST. ? ?
:
, ( , ).
( ).
,
- ( ).
49

web- PSGI/Plack. 2.
, . ,
. ?
Middleware
. , ,
.
, Middleware ( , ), :
Plack::Middleware::MYCOOLMIDDLEWARE,
MYCOOLMIDDLEWARE Middleware.
Plack::Middleware (use parent qw
/Plack::Middleware/;).
() call.
, Middleware :
1
2
3
4
5
6
7

package Plack::Middleware::PostOnly;
use strict;
use warnings;
use parent qw/Plack::Middleware/;
use Plack;
use Plack::Response;
use Plack::Request;

8
9
10

sub call {
my ($self, $env) = @_;

11
12

my $req = Plack::Request>new($env);

13
14
15
16
17
18

if ($req>method() ne 'POST') {
my $new_res = $req>new_response(405);
$new_res>body('Method not allowed');
return $new_res>finalize();
}

19

50

web- PSGI/Plack. 2.
20
21

return $self>app>($env);
}

, . , Plack::Middleware (1 ),
Plack::Middleware (2 ),
call (3 ).
call :
Plack::
Middleware env (my
($self, $env)= @_;).
, (
,
).
, POST, ,
Middleware .
, , POST.
POST Plack::
Response , .
call Middleware 2 .
:
env .
.
, .

51

web- PSGI/Plack. 2.

Pla::Middleware
Pla::Builder
Plack::Middleware::PostOnly,
PSGI , . , :
. . Plack::Builder enable.
enable Plack::Middleware
. :
1
2
3
4

my $main_app = builder {
enable "PostOnly";
mount "/" => builder { $api_app; };
}

. .
PSGI :
1
2

use strict;
use warnings;

3
4
5
6
7

use
use
use
use

Plack;
Plack::Builder;
Plack::Request;
Plack::Middleware::PostOnly;

8
9
10

my $api_app = sub {
my $env = shift;

11
12

warn 'WORKS';

13
14
15

my $req = Plack::Request>new($env);
my $res = $req>new_response(200);

16
17

my $params = $req>parameters();

18
19
20
21
22

if ($params>{string} && $params>{string} eq 'data')


{
$res>body('ok');
}
else {

52

web- PSGI/Plack. 2.
23

$res>body('not ok');

24

}
return $res>finalize();

25
26

};

27
28
29
30
31

my $main_app = builder {
enable "PostOnly";
mount "/" => builder { $api_app };
}

Middleware:
1
2
3
4
5
6
7

package Plack::Middleware::PostOnly;
use strict;
use warnings;
use parent qw/Plack::Middleware/;
use Plack;
use Plack::Response;
use Plack::Request;

8
9
10

sub call {
my ($self, $env) = @_;

11
12

my $req = Plack::Request>new($env);

13
14

if ($req>method() ne 'POST') {
my $new_res = $req>new_response(405);
$new_res>body('Method not allowed');
return $new_res>finalize();
}

15
16
17
18
19
20
21

return $self>app>($env);
}

:
1

/usr/bin/starman port 8080 app.psgi

enable "PostOnly" , Plack


::Builder Plack::
Middleware. enable "PostOnly", enable
"Plack::Middleware::PostOnly" (
+, , enable
"+MyApp::Middleware::PostOnly"; . ).
, http://localhost:8080/ 53

web- PSGI/Plack. 2.
GET, , Method not
allowed 405, POST
.
warn "WORKS".
,
POST. GET, STDERR starman.
PSGI-
, .
Plack::Middleware
, :
.
Middleware.
, PSGI- ,
POST, GET. , Middleware,
GET, , :
1
2
3
4
5
6
7

package Plack::Middleware::GetOnly;
use strict;
use warnings;
use parent qw/Plack::Middleware/;
use Plack;
use Plack::Response;
use Plack::Request;

8
9
10

sub call {
my ($self, $env) = @_;

11
12

my $req = Plack::Request>new($env);

13
14
15
16
17
18

if ($req>method() ne 'GET') {
my $new_res = $req>new_response(405);
$new_res>body('Method not allowed');
return $new_res>finalize();
}

54

web- PSGI/Plack. 2.
19
20
21

return $self>app>($env);
}

, .

:
Middleware.
Middleware .
: . enable Plack::
Builder. , enable . :
1
2
3
4

my $main_app = builder {
enable "Foo", one => 'two', three => 'four';
mount "/" => builder { $api_app };
}

Middleware $self. , , one, $self>{one}


Middleware. PostOnly.
:
1
2
3
4
5
6
7

package Plack::Middleware::GetOnly;
use strict;
use warnings;
use parent qw/Plack::Middleware/;
use Plack;
use Plack::Response;
use Plack::Request;

8
9
10

sub call {
my ($self, $env) = @_;

11
12

my $req = Plack::Request>new($env);

13

55

web- PSGI/Plack. 2.
14

warn $self>{one} if $self>{one};

15
16

if ($req>method() ne 'GET') {
my $new_res = $req>new_response(405);
$new_res>body('Method not allowed');
return $new_res>finalize();
}

17
18
19
20
21
22
23

return $self>app>($env);
}

starman, localhost:8080,
STDERR :
two at /home/noxx/perl/lib/Plack/Middleware/PostOnly.pm
line 12.

Plack::Middleware.
, Middleware, Only.
1
2
3
4
5
6
7

package Plack::Middleware::Only;
use strict;
use warnings;
use parent qw/Plack::Middleware/;
use Plack;
use Plack::Response;
use Plack::Request;

8
9
10

sub call {
my ($self, $env) = @_;

11
12

my $req = Plack::Request>new($env);

13
14

my $method = $self>{method};

15
16

$method ||= 'ANY';

17
18
19
20
21
22

if ($method ne 'ANY' && $req>method() ne $method) {


my $new_res = $req>new_response(405);
$new_res>body('Method not allowed');
return $new_res>finalize();
}

23
24

return $self>app>($env);

56

web- PSGI/Plack. 2.
25

26
27

1;

Middleware .
:
1
2
3
4

my $main_app = builder {
enable "Only", method => 'POST';
mount "/" => builder { $api_app };
};

, POST.
. , , ,
ALLOWED.
, ok, ok
ALLOWED, , ,
.
Only.pm :
1
2
3
4
5
6
7

package Plack::Middleware::Only;
use strict;
use warnings;
use parent qw/Plack::Middleware/;
use Plack;
use Plack::Response;
use Plack::Request;

8
9
10

sub call {
my ($self, $env) = @_;

11
12

my $req = Plack::Request>new($env);

13
14

my $method = $self>{method};

15
16

$method ||= 'ANY';

17
18
19

if ($method ne 'ANY' && $req>method() ne $method) {


my $new_res = $req>new_response(405);

57

web- PSGI/Plack. 2.
20

$new_res>body('Method not allowed');


return $new_res>finalize();

21
22

23
24

my $plack_res = $self>app>($env);
$plack_res>[2]>[0] .= 'ALLOWED';
return $plack_res;

25
26
27

28
29

1;

$self>app>($env) (PSGI-), -

.
, , string=data string=
data1. , ,
okALLOWED, not okALLOWED.
, Plack-. . API, string string=data
ok, not ok, :
/ .
/post
POST.
/get GET.
, , $api_app builder.
, ,
:
1
2

use strict;
use warnings;

58

web- PSGI/Plack. 2.
3
4
5
6
7
8

use
use
use
use
use

Plack;
Plack::Builder;
Plack::Request;
Plack::Middleware::PostOnly;
Plack::Middleware::Only;

9
10
11

my $api_app = sub {
my $env = shift;

12
13

my $req = Plack::Request>new($env);
my $res = $req>new_response(200);

14
15
16

my $params = $req>parameters();

17
18

warn 'RUN!';

19
20

if ($params>{string} && $params>{string} eq 'data')


{
$res>body('ok');
}
else {
$res>body('not ok');
}

21
22
23
24
25
26
27
28

return $res>finalize();
};

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

my $main_app = builder {
mount "/" => builder {
mount "/post" => builder {
enable "Only", method => 'POST';
$api_app;
};
mount "/get" => builder {
enable "Only", method => 'GET';
$api_app;
};
mount "/" => builder {
$api_app;
};
};
};

, Middleware
Plack::Builder.
.
59

web- PSGI/Plack. 2.
(Twiggy, Corona, Feersum).

60

CPAN 2013 .

6. CPAN 2013 .
CPAN .
-.
- Cot
Framework::Core, (Dancer,
Mojolicious, Catalyst, Kossy, Kelp, Amon2, Drogo, Nephia, Dancer2,
). ,
-.

247
849


AnyEvent::Fork AnyEvent-
SockJS SockJS Perl. , javascript SockJS,
, Perl.
Text::YAWikiFormater wiki- html
Digest::SpookyHash
SpookyHash

IO::FDPass . , win32
Crypt::SRP SRP Perl,
,
MITM- .
61

CPAN 2013 .
Language::SNUSP SNUSP, Brainfuck Lemmings.
HTML::Detergent , .. , ,
XPath .
File::Geext / GNU geext po/mo ( libintlperl)
App::cpanminus::reporter cpanm CPAN.
String::Print printf.
Spellunker Perl
Test::Is Test::DescribeMe
. (
Perl QA 2013 ).
Hash::Spy , .
CljPerl Lisp Perl. Lisp CPAN.
Monoceros PSGI/Plack ,
HTTP/1.0,
: .


Perl 5.17.11 Perl . 5.17, 5.18.0 . switch,
62

CPAN 2013 .
~~, given when .
Gitalist 0.004002 - git-
Catalyst.
.
Cache::Memcached::Fast 0.21 Perl Memcashed, C. (tie)
.
AnyEvent::DBI 2.3 DBI. .
Web::ery 0.16 - Jery.
(append, prepend, after, before)
.
App::FatPacker 0.009016 fatpack

perl- . pack, .
DBIx::Class 0.08250 ORM SQL - . , ,
, DBIx::DataModel Rose::DB::Object . cursor(),
10- . SQLite,

DBD::SQLite .
Devel::NYTProf 5.02 Perl. . .
63

CPAN 2013 .
Imager 0.95 Perl
.
.
App::ForkProve v0.4.7 prove,
, fork() ,
,
.
Module::Build.
App::Ack 2.04 grep . ack.
ExtUtils::ParseXS 3.18 XS- C-.
Perl 5.6.x.
ExtUtils::MakeMaker 6.66 Makele.
,
e Number Of e Beast Iron Maiden .
Perl 5.18.
CPAN 2.00 QA CPAN. App::Cpan.
Padre 0.98
IDE Perl Padre. , .

Socket Win32,
IO::Socket::IP.

64

Sawyer X

7. Sawyer X
Sawyer X Perl-,
Dancer, Perl- TelAviv.pm.
.
?
. . , . 10 . , C Pascal. . A Book on
C . , . (
DOS-),
, Windows, GNU/Linux
( GNU/Linux ncurses).
?
Vim ,
. ,
. IDE . Perl Windows,
Padre, Perl IDE. . , , ,
.
Perl?
, Perl. , .
!
65

Sawyer X
?
( , C, C++, Ruby Python) , ,
Perl. ,
, . Perl .. --.. .
, -, Perl?
? . Perl , .
, , ! Devel
::Declare , Perl
. .
, Perl , , .
, Perl!
, -, ?
, . .
, , , , , .
, Perl 6 .
, ,
, , , .
, , ,
, .
, -,
, , , . .
. ,
,
66

Sawyer X
, ,
.
Perl-
open source ?
:
1. . ,
, . - .
. - ! Perl
. Perl ,
.
2. .
, . . . Perl . ,
Perl-
, . . -. ra (Florian Ragwitz .
.)! !
3. . , .
, . Perl .
,
.
. .
.
AnyEvent, ?
POE. -,
, IRC . 67

Sawyer X
, . -
, ?. POE .
, Rocco Caputo, POE.
AnyEvent -
. POE ( Reex ), .
Reex , .
, AnyEvent, (Marc) , , API
AnyEvent. , , . ,
, .
, , AnyEvent
. , .
Dancer . ?
: , DSL,
IRC-.
, .
Dancer, ,
CGI ( PSGI) - , ,
. ,
- Dancer CGI. - Sawyer Dancer, CGI, .
! Alexis Sukrieh, Dancer. ,
. . IRC.
68

Sawyer X
Dancer .
,
, . , ,
Dancer Perl- .
TelAviv.pm .
?
Israel.pm , Shlomi Fish
Gabor Szabo. Shlomi ,
- . TelAviv.pm,
-.
-, 20 -,
. ,
- (
, - ). ( ) ,
, .
, Shlomi Gabor, . ,
- . .
.
, !
:






.
69

Sawyer X
, , , ,
.
, ,
:)
git.
?
Git , - , . , , . Git , . Perl .
. ?
Cluj.pm. .
. ? !
! ! !
. ?
:)
, , Perl-,
, , .
Perl. , ,
, ( ), ,
. - ,
7 Perl, ! Perl -
. , , !
70

Sawyer X
, ,
- . . ,
.
Paul Fenwick . - -?
, Paul ( Paul ),
, .
, ? !
?
Perl? - , , ?
: VoIP
. ,
Perl. 50% Perl
50% . ,
Perl,
( ). Perl. 80%
Perl, , , .

,
. , .

Perl?
! . , , , . ,
, . , , Moose . .
71

Sawyer X
, .
.
, . .


Saywer ?
- . ,
.
. ,
:)
Sawyer,
: ,
!
?
( Perl-
Sawyer . .). . , . , ! , -
,
. , ?
Sebastian Riedel?
. !
Glen Hintle (
Mojolicious- . .), . ,
.

72

Sawyer X
YAPC::Europe ?
, , ,
. ,
, ,
. , :)

73

Perl iz

8. Perl iz
Perl iz Perl-
Perl. ?
.
. , !
: 1) , 2) ,
3) , 4) Perl, 5) 1989, 6) $foo, 7) (Camelia), 8) Windows ME,
9) Python, 10) -
1. Perl ?
1. 0
2. 1
3. 2
4. 3
5. 4
2. Perl?
1. TOP
2. TAP
3. TEP
4. TIP
5. TDD
3. 5.003_97g 5.003_97h?
1. 125
2. 16
3. 42
4. 3
5. 2014
74

Perl iz
4. say say say say 'hi'?
1. "hi"
2. "hi\n1\n1\n1\n"
3.
4.
5. segmentation fault
5. Perl 6?
1. 20
2.
3.
4.
5.
6. kraih?
1. Larry Wall
2.
3. Sebastian Riedel
4. Peter Rabbitson
5. brian d foy
7. MetaCPAN?
1. 14
2. 23
3. 54
4. 78
5. 79
8. PM, Perl-?
1. Perl Monks
75

Perl iz
2. Perl Monsters
3. Perl Mongers
4. Perl Maniacs
5. Perl Machos
9. Perl-?
1.
2. -
3.
4.
5.
10. Perl-?
1. Perl News
2. Perl Weekly
3. Perl Every Week
4. Perl Buzz
5. Perl Pulse

76

Perl-

9. Perl-
.
WebbyLab Perl.
:
Perl 1 .
.
HTML, CSS, JavaScript, jery.
Perl.
.
use strict use warnings!
:
Linux
git/svn.

.
,
/ (A la GitHub, Bitbucket,
SourceForge ..).
:
.
77

Perl-
1 .
.
4 .

78