Commit | Line | Data |
720accfe |
1 | <?xml version="1.0" encoding="utf-8"?> |
2 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" |
3 | "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
4 | |
5 | <html xmlns="http://www.w3.org/1999/xhtml"> |
6 | |
7 | <head> |
8 | <title>Moose</title> |
9 | <!-- metadata --> |
10 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> |
11 | <meta name="generator" content="TextMate/S5" /> |
12 | <meta name="version" content="S5 1.2a2" /> |
13 | <meta name="presdate" content="2008" /> |
14 | <meta name="author" content="Yuval Kogman" /> |
15 | <meta name="company" content="" /> |
16 | <!-- configuration parameters --> |
17 | <meta name="defaultView" content="slideshow" /> |
18 | <meta name="controlVis" content="visible" /> |
19 | <!-- style sheet links --> |
20 | <link rel="stylesheet" href="./ui/moose/slides.css" type="text/css" media="projection" id="slideProj" /> |
21 | <link rel="stylesheet" href="./ui/moose/outline.css" type="text/css" media="screen" id="outlineStyle" /> |
22 | <link rel="stylesheet" href="./ui/moose/print.css" type="text/css" media="print" id="slidePrint" /> |
23 | <link rel="stylesheet" href="./ui/moose/opera.css" type="text/css" media="projection" id="operaFix" /> |
24 | <!-- embedded styles --> |
25 | <style type="text/css" media="all"> |
26 | .imgcon {width: 525px; margin: 0 auto; padding: 0; text-align: center;} |
27 | #anim {width: 270px; height: 320px; position: relative; margin-top: 0.5em;} |
28 | #anim img {position: absolute; top: 42px; left: 24px;} |
29 | img#me01 {top: 0; left: 0;} |
30 | img#me02 {left: 23px;} |
31 | img#me04 {top: 44px;} |
32 | img#me05 {top: 43px;left: 36px;} |
33 | </style> |
34 | <!-- S5 JS --> |
35 | <script src="./ui/moose/slides.js" type="text/javascript"></script> |
36 | </head> |
37 | <body> |
38 | |
39 | <div class="layout"> |
40 | <div id="controls"><!-- DO NOT EDIT --></div> |
41 | <div id="currentSlide"><!-- DO NOT EDIT --></div> |
42 | <div id="header"></div> |
43 | <div id="footer"> |
44 | <h1>YAPC::Asia::2008</h1> |
45 | <h2>Moose</h2> |
46 | </div> |
47 | <div class="topleft"></div> |
48 | <div class="topright"></div> |
49 | <div class="bottomleft"></div> |
50 | <div class="bottomright"></div> |
51 | </div> |
52 | |
53 | <div class="presentation"> |
54 | |
55 | <div class="slide"> |
56 | <h1>Moose</h1> |
57 | <h2></h2> |
58 | <h3>Yuval Kogman</h3> |
59 | <h4></h4> |
60 | </div> |
61 | |
62 | |
63 | <div class="slide"> |
64 | <h1>Moose はなにではないか</h1> |
65 | |
66 | <h2>Moose Is Not</h2> |
67 | |
68 | <ul> |
69 | <li>実験やプロトタイプ (experimental)</li> |
70 | <li>おもちゃ (toy)</li> |
71 | <li>もう一つのアクセサビルダー (accessor builder)</li> |
72 | <li>ソースフィルタ (source filter)</li> |
73 | <li>黒魔術 (black magic)</li> |
74 | <li>Perl 6 in Perl 5</li> |
75 | </ul> |
76 | |
77 | </div> |
78 | |
79 | <div class="slide"> |
80 | <h1>Mooseとはなにか</h1> |
81 | |
82 | <h2>Moose Is</h2> |
83 | |
84 | <ul> |
85 | <li><p>Perlのための完全にモダンなオブジェクトフレームワーク</p></li> |
86 | <li><p>A complete modern object framework for Perl</p></li> |
87 | </ul> |
88 | |
89 | </div> |
90 | |
91 | <div class="slide"> |
92 | <h1>Mooseとはなにか</h1> |
93 | |
94 | <h2>Moose Is</h2> |
95 | |
96 | <ul> |
97 | <li>Class::MOPのためのシンタックスシュガー (Syntactic sugar)</li> |
98 | <li>祖先たち (ancestry) |
99 | <ul> |
100 | <li>CLOS (Common Lisp Object System)</li> |
101 | <li>Smalltalk</li> |
102 | <li>Alces latifrons</li> |
103 | <li>Perl 6</li> |
104 | <li>…</li> |
105 | </ul></li> |
106 | <li>安定していて、お仕事にもつかえます (Stable & Production ready)</li> |
107 | </ul> |
108 | |
109 | </div> |
110 | |
111 | <div class="slide"> |
112 | <h1>シンプルな例</h1> |
113 | |
114 | <h2>A Simple Example</h2> |
115 | |
116 | <pre><code> |
117 | package Person; |
118 | |
119 | use strict; |
120 | use warnings; |
121 | |
122 | sub new { |
123 | my ($class) = @_; |
124 | |
125 | return bless { |
126 | name => '', |
127 | age => undef, |
128 | }, $class; |
129 | } |
130 | |
131 | sub name { |
132 | my ($self, $name) = @_; |
133 | $self->{'name'} = $name if $name; |
134 | return $self->{'name'}; |
135 | } |
136 | |
137 | sub age { |
138 | my ($self, $age) = @_; |
139 | $self->{'age'} = $age if $age; |
140 | return $self->{'age'}; |
141 | } |
142 | |
143 | 1; |
144 | </code></pre> |
145 | |
146 | </div> |
147 | |
148 | <div class="slide"> |
149 | <h1>シンプルなMooseの例</h1> |
150 | |
151 | <h2>A Simple Moose Example</h2> |
152 | |
153 | <pre><code> |
154 | package Person; |
155 | use Moose; |
156 | |
157 | has name => (is => 'rw'); |
158 | has age => (is => 'rw'); |
159 | |
160 | 1; |
161 | </code></pre> |
162 | |
163 | </div> |
164 | |
165 | <div class="slide"> |
166 | <h1>シンプルなMooseの例(つづき)</h1> |
167 | |
168 | <h2>A Simple Moose Example (cont.)</h2> |
169 | |
170 | <ul> |
171 | <li><code>use Moose;</code> |
172 | <ul> |
173 | <li>キーワードをインポート (imports keywords)</li> |
174 | <li><code>use strict; use warnings;</code></li> |
175 | <li><code>@ISA = qw(Moose::Object) unless @ISA</code></li> |
176 | </ul></li> |
177 | </ul> |
178 | |
179 | </div> |
180 | |
181 | <div class="slide"> |
182 | <h1>シンプルなMooseの例(つづき)</h1> |
183 | |
184 | <h2>A Simple Moose Example (cont.)</h2> |
185 | |
186 | <ul> |
187 | <li><p><code>has</code> はアトリビュートを定義する (declares attibutes)</p> |
188 | |
189 | <ul> |
190 | <li>アクセサを生成 (generates accessors)</li> |
191 | <li><code>is => 'rw'</code> → 読み書き両用アクセサ</li> |
192 | <li><code>is => 'ro'</code> → 読み込み専用アクセサ</li> |
193 | <li><code>writer</code>, <code>reader</code></li> |
194 | </ul></li> |
195 | <li><p><code>new</code> は <code>Moose::Object</code> から継承する</p></li> |
196 | </ul> |
197 | |
198 | <div class="notes"> |
199 | <p>今度はアトリビュートの機能を説明していくよ |
200 | Now we’re going to discuss more features of the attributes</p> |
201 | </div> |
202 | </div> |
203 | |
204 | <div class="slide"> |
205 | <h1>Mooseの例のバリエーション</h1> |
206 | |
207 | <h2>Variations on a Moose Example</h2> |
208 | |
209 | <pre><code> |
210 | package Person; |
211 | use Moose; |
212 | |
213 | has name => ( |
214 | is => 'rw', |
215 | isa => 'Str' |
216 | default => 'Bob' |
217 | ); |
218 | |
219 | has staff => ( |
220 | is => 'ro', |
221 | isa => 'ArrayRef', |
222 | lazy => 1, |
223 | default => sub { [qw(Bob Alice Tim)] }, |
224 | ); |
225 | </code></pre> |
226 | |
227 | <div class="notes"> |
228 | <p>default と isa が追加されてます |
229 | Adds default, isa</p> |
230 | </div> |
231 | </div> |
232 | |
233 | <div class="slide"> |
234 | <h1>Mooseの例のバリエーション(つづき)</h1> |
235 | |
236 | <h2>Variations on a Moose Example (cont.)</h2> |
237 | |
238 | <ul> |
239 | <li><p><code>default</code> は</p> |
240 | |
241 | <ul> |
242 | <li>コードリファレンス (coderef)</li> |
243 | <li>またはリファレンス以外 (数値, 文字列) (nonref)</li> |
244 | <li><code>new</code> にパラメータがわたされなかったときに使われる</li> |
245 | </ul></li> |
246 | <li><p><code>lazy</code> は <code>default</code> を遅延させる</p> |
247 | |
248 | <ul> |
249 | <li>最初に <code>$object->staff</code> が使われたときに呼ばれる (generates)</li> |
250 | <li><code>new</code> の中ではなく (no param)</li> |
251 | </ul></li> |
252 | </ul> |
253 | |
254 | <div class="notes"> |
255 | <p>デフォルトの話 |
256 | discusses default</p> |
257 | |
258 | <p>リファレンスでないと想定外の共有がむずかしくなる |
259 | non refs make accidental sharing hard</p> |
260 | </div> |
261 | </div> |
262 | |
263 | <div class="slide"> |
264 | <h1>Mooseの例のバリエーション(つづき)</h1> |
265 | |
266 | <h2>Variations on a Moose Example (cont.)</h2> |
267 | |
268 | <ul> |
269 | <li><code>isa</code> は型を規定する (specifies type) |
270 | <ul> |
271 | <li><code>Moose::Util::TypeConstraints</code> |
272 | <ul> |
273 | <li><code>Any, Item, Bool, Undef, Defined, Value, Num, Int, Str, Ref, ScalarRef, ArrayRef, HashRef, CodeRef, RegexpRef, GlobRef, FileHandle, Object, and Role</code></li> |
274 | </ul></li> |
275 | <li>型は存在する必要はありません (don’t need to exist)</li> |
276 | </ul></li> |
277 | </ul> |
278 | |
279 | <pre><code> |
280 | has 'date' => (isa => 'DateTime'); # DWIM |
281 | </code></pre> |
282 | |
283 | <div class="notes"> |
284 | <p>isa, 型の制約 |
285 | isa, type constraints</p> |
286 | </div> |
287 | </div> |
288 | |
289 | <div class="slide"> |
290 | <h1>型</h1> |
291 | |
292 | <h2>Typical Family</h2> |
293 | |
294 | <ul> |
295 | <li>型は階層構造をもっている (types have a hierarchy) |
296 | <ul> |
297 | <li><code>Item</code> ⊃ <code>Defined</code> ⊃ <code>Ref</code> ⊃ <code>Object</code></li> |
298 | </ul></li> |
299 | </ul> |
300 | |
301 | <pre><code> |
302 | subtype 'Ref' |
303 | => as 'Defined' |
304 | => where { ref($_) }; |
305 | |
306 | subtype 'Object' |
307 | => as 'Ref' |
308 | => where { blessed($_) } |
309 | </code></pre> |
310 | |
311 | <div class="notes"> |
312 | <p>型の階層構造 |
313 | type hierarchy</p> |
314 | </div> |
315 | </div> |
316 | |
317 | <div class="slide"> |
318 | <h1>型の強制変換</h1> |
319 | |
320 | <h2>Some Type of Coercion</h2> |
321 | |
322 | <pre><code> |
323 | package Employee; |
324 | use Moose; |
325 | use Moose::Util::TypeConstraints; |
326 | extends qw(Person); |
327 | |
328 | class_type 'Manager'; |
329 | |
330 | coerce 'Manager' |
331 | => from 'Str' |
332 | => via { Manager->new( name => $_) }; |
333 | |
334 | has manager => ( |
335 | is => 'ro', |
336 | isa => 'Manager', |
337 | required => 1, |
338 | coerce => 1, |
339 | ); |
340 | </code></pre> |
341 | |
342 | </div> |
343 | |
344 | <div class="slide"> |
345 | <h1>型の強制変換(つづき)</h1> |
346 | |
347 | <h2>Some Type of Coercion (cont.)</h2> |
348 | |
349 | <pre><code> |
350 | # 型制約のキーワードをインポート(import type constraint keywords) |
351 | use Moose::Util::TypeConstraints; |
352 | |
353 | |
354 | # オブジェクトのサブタイプであるマネージャーを定義(define Manager, a subtype of Object) |
355 | class_type "Manager"; |
356 | |
357 | |
358 | # 変換を定義する(define the conversion) |
359 | coerce 'Manager' |
360 | => from 'Str' |
361 | => via { Manager->new( name => $_) }; |
362 | |
363 | |
364 | # アトリビュートごとに有効にする(enable it per attribute) |
365 | has manager => ( |
366 | … |
367 | coerce => 1, |
368 | ); |
369 | </code></pre> |
370 | |
371 | <div class="notes"> |
372 | <p>例を細かく見ていくよ |
373 | breakdown of the example</p> |
374 | |
375 | <p>クラスの型はMooseのクラスすべてに自動的に用意されます |
376 | class types are automatically created for all Moose classes</p> |
377 | </div> |
378 | </div> |
379 | |
380 | <div class="slide"> |
381 | <h1>伝統的な委譲</h1> |
382 | |
383 | <h2>Conventional Delegates</h2> |
384 | |
385 | <pre><code> |
386 | package Employee; |
387 | use Moose; |
388 | extends qw(Person); |
389 | |
390 | has manager => ( |
391 | is => 'ro', |
392 | isa => 'Manager', |
393 | handles => { |
394 | manager_name => 'name', |
395 | coworkers => 'staff', |
396 | } |
397 | ); |
398 | </code></pre> |
399 | |
400 | <ul> |
401 | <li>マネージャーは <code>Employee</code> のいくつかのメソッドを処理します</li> |
402 | <li>manager <code>handles</code> certain methods for <code>Employee</code> |
403 | <ul> |
404 | <li><code>$emp->coworkers</code> == <code>$emp->manager->staff</code></li> |
405 | </ul></li> |
406 | </ul> |
407 | |
408 | </div> |
409 | |
410 | <div class="slide"> |
411 | <h1>伝統的な委譲(つづき)</h1> |
412 | |
413 | <h2>Conventional Delegates (cont.)</h2> |
414 | |
415 | <pre><code> |
416 | has phone => ( |
417 | ... |
418 | handles => [qw(number extension)], |
419 | ); |
420 | </code></pre> |
421 | |
422 | </div> |
423 | |
424 | <div class="slide"> |
425 | <h1>伝統的な委譲(つづき)</h1> |
426 | |
427 | <h2>Conventional Delegates (cont.)</h2> |
428 | |
429 | <pre><code> |
430 | has phone => ( |
431 | isa => "Phone" |
432 | handles => qr/$method_regex/, |
433 | ); |
434 | </code></pre> |
435 | |
436 | <ul> |
437 | <li><code>Phone->meta->compute_all_applicable_methods</code>にフィルターをかける</li> |
438 | <li>Filters <code>Phone->meta->compute_all_applicable_methods</code></li> |
439 | </ul> |
440 | |
441 | </div> |
442 | |
443 | <div class="slide"> |
444 | <h1>伝統的な委譲(つづき)</h1> |
445 | |
446 | <h2>Conventional Delegates (cont.)</h2> |
447 | |
448 | <pre><code> |
449 | has phone => ( |
450 | ... |
451 | handles => "Dialing", # a role |
452 | ); |
453 | </code></pre> |
454 | |
455 | </div> |
456 | |
457 | <div class="slide"> |
458 | <h1>伝統的じゃない委譲</h1> |
459 | |
460 | <h2>UnConventional Delegates</h2> |
461 | |
462 | <pre><code> |
463 | package Company; |
464 | use Moose; |
465 | use MooseX::AttributeHelpers; |
466 | |
467 | has employees => ( |
468 | metaclass => 'Collection::Array', |
469 | isa => 'ArrayRef[Employees]', |
470 | is => 'rw', |
471 | provides => { |
472 | push => 'add_employee', |
473 | pop => 'remove_employee', |
474 | count => 'number_of_employees', |
475 | empty => 'any_employees', |
476 | } |
477 | ); |
478 | </code></pre> |
479 | |
480 | </div> |
481 | |
482 | <div class="slide"> |
483 | <h1>メソッド変更のセカイ</h1> |
484 | |
485 | <h2>Modified Methods</h2> |
486 | |
487 | <pre><code> |
488 | before 'employees' => sub { warn 'calling employees' }; |
489 | |
490 | after 'employees' => sub { warn 'finished calling employees' }; |
491 | </code></pre> |
492 | |
493 | <ul> |
494 | <li>現在のメソッドが実行される前/された後に実行されます</li> |
495 | <li>Pre/Post hooks |
496 | <ul> |
497 | <li><code>@_</code>のコピーを得ます(Get a copy of <code>@_</code>)</li> |
498 | <li>返り値は無視されます(Return value is ignored)</li> |
499 | </ul></li> |
500 | </ul> |
501 | |
502 | </div> |
503 | |
504 | <div class="slide"> |
505 | <h1>メソッド変更のセカイ(つづき)</h1> |
506 | |
507 | <h2>Modified Methods (cont.)</h2> |
508 | |
509 | <pre><code> |
510 | around 'employees' => sub { |
511 | my ($next, $self, @args) = @_; |
512 | ... |
513 | my @return = $self->$next(@args); |
514 | ... |
515 | return @return; |
516 | }; |
517 | </code></pre> |
518 | |
519 | </div> |
520 | |
521 | <div class="slide"> |
522 | <h1>メソッド変更のセカイ(つづき)</h1> |
523 | |
524 | <h2>Modified Methods (cont.)</h2> |
525 | |
526 | <pre><code> |
527 | package Employee; |
528 | use Moose; |
529 | |
530 | sub do_work { |
531 | my $self = shift; |
532 | |
533 | $self->punch_in; |
534 | |
535 | inner(); # call subclass here |
536 | |
537 | $self->punch_out; |
538 | } |
539 | </code></pre> |
540 | |
541 | </div> |
542 | |
543 | <div class="slide"> |
544 | <h1>メソッド変更のセカイ(つづき)</h1> |
545 | |
546 | <h2>Modified Methods (cont.)</h2> |
547 | |
548 | <pre><code> |
549 | package Employee::Chef; |
550 | use Moose; |
551 | |
552 | extends qw(Employee); |
553 | |
554 | augment do_work => sub { |
555 | my $self = shift; |
556 | |
557 | while ( @burgers ) { |
558 | $self->flip_burger(shift @burgers); |
559 | } |
560 | } |
561 | |
562 | $chef->do_work; # punch in, flip burgers, punch out |
563 | </code></pre> |
564 | |
565 | </div> |
566 | |
567 | <div class="slide"> |
568 | <h1>型についての余談</h1> |
569 | |
570 | <h2>Some Type of Digression</h2> |
571 | |
572 | <pre><code> |
573 | has employees => ( |
574 | is => 'rw', |
575 | isa => 'ArrayRef[Employee]', |
576 | ); |
577 | |
578 | has shopping_carts => ( |
579 | is => 'rw', |
580 | isa => 'ArrayRef[ArrayRef[ShinyBead]]' |
581 | ); |
582 | </code></pre> |
583 | |
584 | <div class="notes"> |
585 | <p>型システムの機能についてちょっと説明していくよ |
586 | Going to go into features of the type system for a bit</p> |
587 | |
588 | <p>パラメータ付きの型 |
589 | Parametrized types</p> |
590 | </div> |
591 | </div> |
592 | |
593 | <div class="slide"> |
594 | <h1>型についての余談(つづき)</h1> |
595 | |
596 | <h2>Some Type of Digression (cont.)</h2> |
597 | |
598 | <pre><code> |
599 | has language => ( |
600 | is => 'rw', |
601 | isa => 'English | Welsh | Scots | Gaelic', |
602 | ); |
603 | |
604 | has member => ( |
605 | is => 'rw', |
606 | isa => 'Employee | ArrayRef[Employee|Group]', |
607 | ); |
608 | </code></pre> |
609 | |
610 | <div class="notes"> |
611 | <p>型の結合 |
612 | Union types</p> |
613 | </div> |
614 | </div> |
615 | |
616 | <div class="slide"> |
617 | <h1>型についての余談(つづき)</h1> |
618 | |
619 | <h2>Some Type of Digression (cont.)</h2> |
620 | |
621 | <pre><code> |
622 | package Foo; |
623 | use Moose; |
624 | use Moose::Util::TypeConstraints; |
625 | use Test::Deep qw(eq_deeply ...); |
626 | |
627 | type 'SomethingTricky' |
628 | => where { |
629 | eq_deeply( $_, ... ); |
630 | }; |
631 | |
632 | has 'bar' => ( |
633 | is => 'rw', |
634 | isa => 'SomethingTricky', |
635 | ); |
636 | </code></pre> |
637 | |
638 | <div class="notes"> |
639 | <p>Test::Deppのカスタムバリデータ |
640 | Test::Deep custom validator</p> |
641 | |
642 | <p>CPANからどんなバリデータでも持ってこられる |
643 | Can use any validation from the CPAN</p> |
644 | </div> |
645 | </div> |
646 | |
647 | <div class="slide"> |
648 | <h1>パラメータ付きの型の強制変換</h1> |
649 | |
650 | <h2>Some Parametrized Type of Coercion</h2> |
651 | |
652 | <pre><code> |
653 | use Moose::Util::TypeConstraints; |
654 | subtype 'ArrayRef[Employee]' => as 'ArrayRef'; |
655 | |
656 | coerce 'ArrayRef[Employee]' |
657 | => from 'ArrayRef[Str]' |
658 | => via { [ map { Employee->new( name => $_ ) } @$_ ] }; |
659 | |
660 | has staff => ( |
661 | is => 'ro', |
662 | isa => 'ArrayRef[Employee]', |
663 | lazy => 1, |
664 | default => sub { [qw(Bob Alice Tim)] }, |
665 | coerce => 1, |
666 | ); |
667 | </code></pre> |
668 | |
669 | <div class="notes"> |
670 | <p>ArrayRef[Str] から ArrayRef[Employee] に強制変換 |
671 | coerce parametrized ArrayRef[Employee] from ArrayRef[Str]</p> |
672 | |
673 | <p>強制変換は ‘default’ の返り値にも適用されます |
674 | coercions can be applied to ‘default’ return values</p> |
675 | </div> |
676 | </div> |
677 | |
678 | <div class="slide"> |
679 | <h1>MooseのRole </h1> |
680 | |
681 | <h2>Role of the Moose</h2> |
682 | |
683 | <ul> |
684 | <li>Role は…(A role is like a) |
685 | <ul> |
686 | <li>JavaのInterfaceみたい</li> |
687 | <li>mixinみたい</li> |
688 | <li>…それでいて安全でパワフル(safe, powerful)</li> |
689 | </ul></li> |
690 | <li>Role は小さくて再利用可能な動作向け(A role is for small reusable behaviors) |
691 | <ul> |
692 | <li>多重継承よりよい(better than using a multiple inheritence)</li> |
693 | </ul></li> |
694 | </ul> |
695 | |
696 | </div> |
697 | |
698 | <div class="slide"> |
699 | <h1>MooseのRole(つづき)</h1> |
700 | |
701 | <h2>Role of the Moose (cont.)</h2> |
702 | |
703 | <ul> |
704 | <li>CPAN にある Role たち(Roles on the CPAN): |
705 | <ul> |
706 | <li><code>MooseX::Storage</code> - 柔軟なシリアライズ(Flexible serialization)</li> |
707 | <li><code>MooseX::LogDispatch</code> - <code>$self->logger->info("something happenned")</code></li> |
708 | <li><code>MooseX::Getopt</code> - コマンドライン引数の処理(<code>@ARGV</code> aware constructor)</li> |
709 | <li><code>MooseX::Param</code> - <code>CGI.pm</code> の <code>param()</code> メソッドみたいなの(<code>param</code> method like <code>CGI.pm</code>’s)</li> |
710 | <li><code>MooseX::Clone</code> - 柔軟な<code>clone</code>メソッド(Flexible <code>clone</code> method)</li> |
711 | </ul></li> |
712 | </ul> |
713 | |
714 | <div class="notes"> |
715 | <p>再利用可能な小さな動作の例 |
716 | Some examples of small reusable behaviors</p> |
717 | |
718 | <p>Paramは連携に便利 |
719 | Param is good for interacting with e.g. CGI::Expand or similar modules</p> |
720 | </div> |
721 | </div> |
722 | |
723 | <div class="slide"> |
724 | <h1>MooseのRole(つづき)</h1> |
725 | |
726 | <h2>Role of the Moose (cont.)</h2> |
727 | |
728 | <pre><code> |
729 | package Minion; |
730 | use Moose; |
731 | |
732 | extends qw(Employee); |
733 | |
734 | with qw(Salaried::Hourly); |
735 | |
736 | package Boss; |
737 | use Moose; |
738 | |
739 | extends qw(Employee); |
740 | |
741 | with qw(Salaried::Monthly); |
742 | |
743 | </code></pre> |
744 | |
745 | <ul> |
746 | <li><code>with</code> はクラスに Role を追加します</li> |
747 | <li><code>with</code> adds roles into your class |
748 | <ul> |
749 | <li><code>Salaried::Hourly</code>が<code>Minion</code>に追加される</li> |
750 | <li><code>Salaried::Hourly</code> was added to <code>Minion</code></li> |
751 | </ul></li> |
752 | </ul> |
753 | |
754 | </div> |
755 | |
756 | <div class="slide"> |
757 | <h1>MooseのRole(つづき)</h1> |
758 | |
759 | <h2>Role of the Moose (cont.)</h2> |
760 | |
761 | <pre><code> |
762 | package Salaried; |
763 | use Moose::Role; |
764 | |
765 | requires qw('paycheck_amount'); |
766 | </code></pre> |
767 | |
768 | <ul> |
769 | <li>単なるインターフェース</li> |
770 | <li>Just an interface</li> |
771 | </ul> |
772 | |
773 | </div> |
774 | |
775 | <div class="slide"> |
776 | <h1>MooseのRole(つづき)</h1> |
777 | |
778 | <h2>Role of the Moose (cont.)</h2> |
779 | |
780 | <pre><code> |
781 | package Salaried::Hourly; |
782 | use Moose::Role; |
783 | |
784 | with qw(Salaried); |
785 | |
786 | has hourly_rate => ( |
787 | isa => "Num", |
788 | is => "rw", |
789 | required => 1, |
790 | ); |
791 | |
792 | has logged_hours => ( |
793 | isa => "Num", |
794 | is => "rw", |
795 | default => 0, |
796 | ); |
797 | |
798 | sub paycheck_amount { |
799 | my $self = shift; |
800 | |
801 | $self->logged_hours * $self->hourly_rate; |
802 | } |
803 | |
804 | </code></pre> |
805 | |
806 | <ul> |
807 | <li>インターフェースよりイイネ!</li> |
808 | <li>More than an interface</li> |
809 | </ul> |
810 | |
811 | </div> |
812 | |
813 | <div class="slide"> |
814 | <h1>MooseのRole(つづき)</h1> |
815 | |
816 | <h2>Role of the Moose (cont.)</h2> |
817 | |
818 | <ul> |
819 | <li>Javaのインターフェースよりイイネ!</li> |
820 | <li>More than Java Interfaces |
821 | <ul> |
822 | <li>インターフェースは挙動の’規定’を提供する</li> |
823 | <li>Interfaces are behavior “contracts”</li> |
824 | <li>Role は挙動の’実装’も提供できる</li> |
825 | <li>Roles can also have code</li> |
826 | </ul></li> |
827 | </ul> |
828 | |
829 | <div class="notes"> |
830 | <p>Roleはアトリビュートとメソッドを持てる |
831 | roles can have attributes and methods |
832 | Roleはインターフェースだけでなく動作を提供するもの |
833 | roles provide behavior, not just interface</p> |
834 | </div> |
835 | </div> |
836 | |
837 | <div class="slide"> |
838 | <h1>MooseのRole(つづき)</h1> |
839 | |
840 | <h2>Role of the Moose (cont.)</h2> |
841 | |
842 | <ul> |
843 | <li>Roleの組み込み(Role Composition) |
844 | <ul> |
845 | <li>継承ではない(Not inheritence)</li> |
846 | <li>喧嘩両成敗(Symmetric)</li> |
847 | <li>順序は関係ない(Unordered)</li> |
848 | </ul></li> |
849 | </ul> |
850 | |
851 | </div> |
852 | |
853 | <div class="slide"> |
854 | <h1>MooseのRole(つづき)</h1> |
855 | |
856 | <h2>Role of the Moose (cont.)</h2> |
857 | |
858 | <ul> |
859 | <li>Roleの組み込み(Role Composition) |
860 | <ul> |
861 | <li>あいまいさが少ない(Less ambiguity)</li> |
862 | <li>コンパイル時エラー(Compile time errors)</li> |
863 | <li>…修正する方法もある(And ways to fix them)</li> |
864 | </ul></li> |
865 | </ul> |
866 | |
867 | <div class="notes"> |
868 | <p>喧嘩両成敗というのは優先順位がないということ。ふたつのRoleが同じものを定義しようとした場合はコンパイル時にエラーになる(直さないといけない) |
869 | symmetric composition means no precedence - if two roles try to define the same thing you get a compile time error that needs to be resolved |
870 | 多重継承の場合はだまって最初のクラスを使うもんだと想定してしまう |
871 | multiple inheritence silently assumes you want the first class</p> |
872 | |
873 | <p>Roleは多重継承と違ってコンパイル時にエラーを吐く |
874 | roles cause errors at compile time, unlike multiple inheritence</p> |
875 | |
876 | <p>Roleは簡単にエラーを修正する方法も用意している |
877 | roles also provide easy ways to fix the errors</p> |
878 | </div> |
879 | </div> |
880 | |
881 | <div class="slide"> |
882 | <h1>MooseのRole(つづき)</h1> |
883 | |
884 | <h2>Role of the Moose (cont.)</h2> |
885 | |
886 | <pre><code> |
887 | package First; |
888 | use Moose::Role; |
889 | |
890 | sub dancing { ... } |
891 | |
892 | package Second; |
893 | use Moose::Role |
894 | |
895 | sub dancing { ... } |
896 | |
897 | package Foo; |
898 | use Moose; |
899 | |
900 | # KABOOM |
901 | with qw( |
902 | First |
903 | Second |
904 | ); |
905 | </code></pre> |
906 | |
907 | <div class="notes"> |
908 | <p>衝突 |
909 | conflicts</p> |
910 | </div> |
911 | </div> |
912 | |
913 | <div class="slide"> |
914 | <h1>MooseのRole(つづき)</h1> |
915 | |
916 | <h2>Role of the Moose (cont.)</h2> |
917 | |
918 | <pre><code> |
919 | package Ent::Puppy; |
920 | use Moose; |
921 | |
922 | with ( |
923 | Tree => { |
924 | alias => { |
925 | bark => "tree_bark", |
926 | }, |
927 | }, |
928 | Dog => { |
929 | alias => { |
930 | bark => "bark_sound", |
931 | } |
932 | }, |
933 | ); |
934 | |
935 | sub bark { |
936 | my $self = shift; |
937 | |
938 | if ( $condition ) { |
939 | $self->tree_bark; |
940 | } else { |
941 | $self->bark_sound; |
942 | } |
943 | } |
944 | </code></pre> |
945 | |
946 | <div class="notes"> |
947 | <p>組み込むときにパラメータをつける |
948 | Composition parameters |
949 | 衝突を解決するのも簡単だし |
950 | Easier conflict resolution |
951 | よりきめ細かいコントロールができるようになる |
952 | Finer grained control</p> |
953 | </div> |
954 | </div> |
955 | |
956 | <div class="slide"> |
957 | <h1>MOPはキレイ</h1> |
958 | |
959 | <h2>MOPs Mean Cleanliness</h2> |
960 | |
961 | <ul> |
962 | <li>Moose は Class::MOP でつくられてる</li> |
963 | <li>Moose is based on <code>Class::MOP</code> |
964 | <ul> |
965 | <li>Perl5のためのメタオブジェクトプロトコル(Metaobject Protocol for Perl 5)</li> |
966 | <li>すべてにオブジェクトがつくられる(“makes an object for everything”)</li> |
967 | </ul></li> |
968 | </ul> |
969 | |
970 | <pre><code> |
971 | my $class = $obj->meta; # $objのメタクラス($obj's metaclass) |
972 | my $meta = MyApp->meta; # MyAppのメタクラス(MyApp's metaclass) |
973 | my $emo = $obj->meta->meta # メタメタ(even more meta)! |
974 | |
975 | warn $obj->meta->name; |
976 | </code></pre> |
977 | |
978 | </div> |
979 | |
980 | <div class="slide"> |
981 | <h1>内側からみてみる</h1> |
982 | |
983 | <h2>Looking in From the Inside</h2> |
984 | |
985 | <pre><code> |
986 | my $metaclass = $self->meta; |
987 | |
988 | $metaclass->superclasses; |
989 | |
990 | $metaclass->linearized_isa; # すべての先祖クラスを得ます(returns all ancestors) |
991 | |
992 | $metaclass->has_method("foo"); |
993 | |
994 | $metaclass->compute_all_applicable_methods; # すべてのメソッド(継承されたものもふくめて)(returns all methods (inherited too)) |
995 | |
996 | $metaclass->has_attribute("bar"); |
997 | |
998 | # … lots more |
999 | </code></pre> |
1000 | |
1001 | <div class="notes"> |
1002 | <p>simple introspection</p> |
1003 | </div> |
1004 | </div> |
1005 | |
1006 | <div class="slide"> |
1007 | <h1>内側からみてみる(つづき)</h1> |
1008 | |
1009 | <h2>Looking in From the Inside (cont.)</h2> |
1010 | |
1011 | <pre><code> |
1012 | Moose::Meta::Class->create( Bar => |
1013 | version => '0.01', |
1014 | superclasses => [ 'Foo' ], |
1015 | attributes => [ |
1016 | Moose::Meta::Attribute->new( bar => ... ), |
1017 | Moose::Meta::Attribute->new( baz => ... ), |
1018 | ], |
1019 | methods => { |
1020 | calculate_bar => sub { ... }, |
1021 | construct_baz => sub { ... } |
1022 | } |
1023 | ); |
1024 | </code></pre> |
1025 | |
1026 | <div class="notes"> |
1027 | <p>クラスはプログラム的につくることもできる |
1028 | Classes can be created programmatically</p> |
1029 | |
1030 | <p>無名クラスも可 |
1031 | Anonymous classes also possible</p> |
1032 | </div> |
1033 | </div> |
1034 | |
1035 | <div class="slide"> |
1036 | <h1>内側からみてみる(つづき)</h1> |
1037 | |
1038 | <h2>Looking in From the Inside (cont.)</h2> |
1039 | |
1040 | <pre><code> |
1041 | has foo => ( is => "rw" ); |
1042 | |
1043 | __PACKAGE__->meta->add_attribute( foo => is => "rw" ); |
1044 | </code></pre> |
1045 | |
1046 | <ul> |
1047 | <li>Mooseは単なるシュガー(Moose is just sugar) |
1048 | <ul> |
1049 | <li>大変な部分はMOPがしてくれる(The MOP does the hard work)</li> |
1050 | </ul></li> |
1051 | </ul> |
1052 | |
1053 | </div> |
1054 | |
1055 | <div class="slide"> |
1056 | <h1>メタクラスのタンゴ</h1> |
1057 | |
1058 | <h2>The Metaclass Tango</h2> |
1059 | |
1060 | <ul> |
1061 | <li>メタクラスはクラスの挙動をコントロールする</li> |
1062 | <li>Metaclassses control class behavior</li> |
1063 | </ul> |
1064 | |
1065 | <pre><code> |
1066 | has employees => ( |
1067 | metaclass => 'Collection::Array', |
1068 | ... |
1069 | ); |
1070 | </code></pre> |
1071 | |
1072 | <ul> |
1073 | <li>カスタムアトリビュートメタクラスは</li> |
1074 | <li>custom attribute metaclasses |
1075 | <ul> |
1076 | <li>アトリビュートがどういう風に動くかを変える</li> |
1077 | <li>change how attributes work</li> |
1078 | </ul></li> |
1079 | <li>カスタマイズ可能なパーツたち</li> |
1080 | <li>Many customizable parts |
1081 | <ul> |
1082 | <li><code>Moose::Meta::Class</code>, <code>Moose::Meta::Attribute,</code><code>Moose::Meta::Method</code>, <code>Moose::Meta::Method::Accessor</code> <code>Moose::Meta::Instance</code>, <code>Moose::Meta::Role</code>, <code>Moose::Meta::TypeConstraint</code>, …,</li> |
1083 | </ul></li> |
1084 | </ul> |
1085 | |
1086 | </div> |
1087 | |
1088 | <div class="slide"> |
1089 | <h1>メタフレームを使う</h1> |
1090 | |
1091 | <h2>Working in the Meta Frame</h2> |
1092 | |
1093 | <ul> |
1094 | <li>仕事であったおもろい話(An interesting <code>$work</code> story)</li> |
1095 | <li>flashを使ったサイト用のCMS(CMS for a flash website)</li> |
1096 | <li>コンテンツはXML(Content is in XML)</li> |
1097 | </ul> |
1098 | |
1099 | </div> |
1100 | |
1101 | <div class="slide"> |
1102 | <h1>メタフレームを使う(つづき)</h1> |
1103 | |
1104 | <h2>Working in the Meta Frame (cont.)</h2> |
1105 | |
1106 | <ul> |
1107 | <li>Step 1. use Moose</li> |
1108 | <li>Step 2. ???</li> |
1109 | <li>Step 3. 金(Profit)!</li> |
1110 | </ul> |
1111 | |
1112 | </div> |
1113 | |
1114 | <div class="slide"> |
1115 | <h1>メタフレームを使う(つづき)</h1> |
1116 | |
1117 | <h2>Working in the Meta Frame (cont.)</h2> |
1118 | |
1119 | <ul> |
1120 | <li>Step 2.1. XMLスキーマ(schemas) → クラス(classes) |
1121 | <ul> |
1122 | <li>自動変換(Automatic conversion) |
1123 | <ul> |
1124 | <li>MOPのおかげで楽勝(MOP makes it easy)</li> |
1125 | </ul></li> |
1126 | <li>実行時には高レベルオブジェクト(High level objects in runtime)</li> |
1127 | <li>裏ではXML(XML backed) |
1128 | <ul> |
1129 | <li>クライアントのスキーマ(With client’s schemas)</li> |
1130 | <li>SAX → Moose</li> |
1131 | <li>Moose → SAX</li> |
1132 | </ul></li> |
1133 | </ul></li> |
1134 | </ul> |
1135 | |
1136 | </div> |
1137 | |
1138 | <div class="slide"> |
1139 | <h1>メタフレームを使う(つづき)</h1> |
1140 | |
1141 | <h2>Working in the Meta Frame (cont.)</h2> |
1142 | |
1143 | <ul> |
1144 | <li>Step 2.2. メタ記述(Meta descriptions) |
1145 | <ul> |
1146 | <li>メタクラスを拡張(Extend the metaclasses)</li> |
1147 | <li>追加の情報を埋め込む(Embed additional information) |
1148 | <ul> |
1149 | <li>フィールド型(field types)</li> |
1150 | <li>アクセスコントロール(access control)</li> |
1151 | </ul></li> |
1152 | </ul></li> |
1153 | </ul> |
1154 | |
1155 | </div> |
1156 | |
1157 | <div class="slide"> |
1158 | <h1>メタフレームを使う(つづき)</h1> |
1159 | |
1160 | <h2>Working in the Meta Frame (cont.)</h2> |
1161 | |
1162 | <ul> |
1163 | <li>Step 2.3 イントロスペクションかわゆす(Introspection goodness) |
1164 | <ul> |
1165 | <li>汎用Webフロントエンド(Generic web frontend)</li> |
1166 | <li>オブジェクトイントロスペクションベース(Object introspection based) |
1167 | <ul> |
1168 | <li>HTMLビュー(view)</li> |
1169 | <li>編集用のウィジェット(Editing widgets)</li> |
1170 | </ul></li> |
1171 | <li>クリーンで拡張性も高い(Clean, extensible)</li> |
1172 | </ul></li> |
1173 | </ul> |
1174 | |
1175 | </div> |
1176 | |
1177 | <div class="slide"> |
1178 | <h1>Moose の欠点</h1> |
1179 | |
1180 | <h2>Drawbacks of Moose</h2> |
1181 | |
1182 | <ul> |
1183 | <li>ロード時間(Load time) |
1184 | <ul> |
1185 | <li><code>MooseX::Compile</code> がアルでよ(<code>MooseX::Compile</code> is in the works)</li> |
1186 | </ul></li> |
1187 | <li>いくつかの機能が遅い(Some features are slow) |
1188 | <ul> |
1189 | <li>でも、あなたがつかったぶんだけだから(but you only pay for what you use)</li> |
1190 | </ul></li> |
1191 | <li>hashref じゃないクラスの拡張はトリッキー(Extending non-Hash based classes is tricky). |
1192 | <ul> |
1193 | <li>でも可能(but possible): <code>MooseX::GlobRef::Object</code></li> |
1194 | </ul></li> |
1195 | </ul> |
1196 | |
1197 | </div> |
1198 | |
1199 | <div class="slide"> |
1200 | <h1>Mooseのイイ!とこ</h1> |
1201 | |
1202 | <h2>Benefits of Moose</h2> |
1203 | |
1204 | <ul> |
1205 | <li>退屈なことを減らせる(Less tedious) |
1206 | <ul> |
1207 | <li>決まり文句を書かなくていい(ditch that boilerplate): |
1208 | <ul> |
1209 | <li>アトリビュートのストレージ/アクセサ(attribute storage/access)</li> |
1210 | <li>コンストラクタ(construction)</li> |
1211 | <li>デストラクタ(destruction)</li> |
1212 | <li>引数検査(verification)</li> |
1213 | <li>…</li> |
1214 | </ul></li> |
1215 | <li>繰り返しを減らせる(less repetition)</li> |
1216 | <li>typo を減らせる(fewer typos)</li> |
1217 | </ul></li> |
1218 | </ul> |
1219 | |
1220 | </div> |
1221 | |
1222 | <div class="slide"> |
1223 | <h1>Mooseのイイ!とこ(つづき)</h1> |
1224 | |
1225 | <h2>Benefits of Moose (cont.)</h2> |
1226 | |
1227 | <ul> |
1228 | <li>みじかい(Shorter) |
1229 | <ul> |
1230 | <li>declarative == 情報がおおく、タイプ数がすくない(more info, less typing)</li> |
1231 | <li>no RSI ;-)</li> |
1232 | <li>コードがすくなきゃバグもすくなかろう(less code means fewer bugs)</li> |
1233 | </ul></li> |
1234 | </ul> |
1235 | |
1236 | </div> |
1237 | |
1238 | <div class="slide"> |
1239 | <h1>Mooseのイイ!とこ(つづき)</h1> |
1240 | |
1241 | <h2>Benefits of Moose (cont.)</h2> |
1242 | |
1243 | <ul> |
1244 | <li>テストがすくなくていい(Less testing) |
1245 | <ul> |
1246 | <li>Moose はよくテストされておる</li> |
1247 | <li>Moose is well tested |
1248 | <ul> |
1249 | <li>アクセサやら挙動やらをチェックせんでもよろし</li> |
1250 | <li>no need to check accessor behavior, etc</li> |
1251 | </ul></li> |
1252 | <li>あなたのコードの目的にフォーカスできます!</li> |
1253 | <li>focus on your code’s purpose |
1254 | <ul> |
1255 | <li>きちんと「まとめて」おかなくてもいいよ</li> |
1256 | <li>not that it is “assembled” correctly</li> |
1257 | <li>http://c2.com/cgi/wiki?IntentionNotAlgorithm</li> |
1258 | </ul></li> |
1259 | </ul></li> |
1260 | </ul> |
1261 | |
1262 | </div> |
1263 | |
1264 | <div class="slide"> |
1265 | <h1>Mooseのイイ!とこ(つづき)</h1> |
1266 | |
1267 | <h2>Benefits of Moose (cont.)</h2> |
1268 | |
1269 | <ul> |
1270 | <li>読みやすい(More readable) |
1271 | <ul> |
1272 | <li>宣言的なスタイルだからそのまま文書になっている</li> |
1273 | <li>declarative style is self documenting</li> |
1274 | <li>やりたいことを書け。関係ないOOのしかけとかはあまり書かなくてもいい</li> |
1275 | <li>Code your intentions, not and OO mechanics less</li> |
1276 | </ul></li> |
1277 | </ul> |
1278 | |
1279 | </div> |
1280 | |
1281 | <div class="slide"> |
1282 | <h1>Mooseのイイ!とこ(つづき)</h1> |
1283 | |
1284 | <h2>Benefits of Moose (cont.)</h2> |
1285 | |
1286 | <ul> |
1287 | <li>Meta object protocol |
1288 | <ul> |
1289 | <li>Perl の OO を綺麗にあつかえます</li> |
1290 | <li>Cleans up all levels of Perl’s OO</li> |
1291 | <li>イントロスペクションできます</li> |
1292 | <li>Provides introspection</li> |
1293 | <li>パワフルな抽象化</li> |
1294 | <li>Enables powerful abstractions</li> |
1295 | </ul></li> |
1296 | </ul> |
1297 | |
1298 | </div> |
1299 | |
1300 | <div class="slide"> |
1301 | <h1>Mooseのイイ!とこ(つづき)</h1> |
1302 | |
1303 | <h2>Benefits of Moose (cont.)</h2> |
1304 | |
1305 | <ul> |
1306 | <li>今年の流行だよ</li> |
1307 | <li>It’s the new black |
1308 | <ul> |
1309 | <li>イカした連中はみんな#mooseにきている</li> |
1310 | <li>All the cool kids hang out on #moose</li> |
1311 | <li>かっこよさげなバズワード</li> |
1312 | <li>Smart sounding buzzwords</li> |
1313 | <li>2007年にはRubyがそうだったね</li> |
1314 | <li>Ruby is so 2007</li> |
1315 | </ul></li> |
1316 | </ul> |
1317 | |
1318 | </div> |
1319 | |
1320 | <div class="slide"> |
1321 | <h1>おまけ</h1> |
1322 | |
1323 | <h2>Bonus Material</h2> |
1324 | |
1325 | </div> |
1326 | |
1327 | <div class="slide"> |
1328 | <h1>Autobox</h1> |
1329 | |
1330 | <pre><code> |
1331 | package Units::Bytes; |
1332 | use Moose::Role; |
1333 | use Moose::Autobox; |
1334 | |
1335 | sub bytes { $_[0] } |
1336 | sub kilobytes { $_[0] * 1024 } |
1337 | sub megabytes { $_[0] * 1024->kilobytes } |
1338 | sub gigabytes { $_[0] * 1024->megabytes } |
1339 | sub terabytes { $_[0] * 1024->gigabytes } |
1340 | |
1341 | Moose::Autobox->mixin_additional_role(SCALAR => 'Units::Bytes'); |
1342 | </code></pre> |
1343 | |
1344 | </div> |
1345 | |
1346 | <div class="slide"> |
1347 | <h1>Autobox (つづき)</h1> |
1348 | |
1349 | <h2>Autobox (cont.)</h2> |
1350 | |
1351 | <pre><code> |
1352 | use Units::Bytes; |
1353 | use Moose::Autobox; |
1354 | |
1355 | is(5->bytes, 5, '... got 5 bytes'); |
1356 | is(5->kilobytes, 5120, '... got 5 kilobytes'); |
1357 | is(2->megabytes, 2097152, '... got 2 megabytes'); |
1358 | is(1->gigabytes, 1073741824, '... got 1 gigabyte'); |
1359 | is(2->terabytes, 2199023255552, '... got 2 terabyte'); |
1360 | </code></pre> |
1361 | |
1362 | </div> |
1363 | |
1364 | <div class="slide"> |
1365 | <h1>perl -Moose</h1> |
1366 | |
1367 | <ul> |
1368 | <li>Moose なワンライナーには <code>oose.pm</code> があるでよ</li> |
1369 | <li>Moose One Liners with <code>oose.pm</code></li> |
1370 | </ul> |
1371 | |
1372 | <pre><code> |
1373 | perl -Moose -e'has foo => (is=>q[rw]); Class->new(foo=>1)' |
1374 | </code></pre> |
1375 | |
1376 | <ul> |
1377 | <li>なんかためしたいときなどに</li> |
1378 | <li>Useful for testing if something works</li> |
1379 | <li>IRC での会話には欠かせませんな!</li> |
1380 | <li>Nice for IRC</li> |
1381 | </ul> |
1382 | |
1383 | </div> |
1384 | |
1385 | <div class="slide"> |
1386 | <h1>MooseX::POE</h1> |
1387 | |
1388 | <pre><code> |
1389 | package Counter; |
1390 | use MooseX::POE; |
1391 | |
1392 | has count => ( |
1393 | isa => 'Int', |
1394 | is => 'rw', |
1395 | ); |
1396 | |
1397 | sub START { |
1398 | my ($self) = @_; |
1399 | $self->yield('increment'); |
1400 | } |
1401 | |
1402 | event increment => sub { |
1403 | my ($self) = @_; |
1404 | warn "Count is now " . $self->count; |
1405 | $self->count( $self->count + 1 ); |
1406 | $self->yield('increment') unless $self->count > 3; |
1407 | }; |
1408 | |
1409 | Counter->new( count => 0 ); |
1410 | POE::Kernel->run(); |
1411 | </code></pre> |
1412 | |
1413 | <ul> |
1414 | <li>POE のコンポーネントを簡単にかけます</li> |
1415 | <li>POE components made easy</li> |
1416 | <li>それぞれのオブジェクトが POE::Session をもってます</li> |
1417 | <li>Every object has a POE::Session</li> |
1418 | <li><code>event</code> がオブジェクトのステートを宣言します</li> |
1419 | <li><code>event</code> declares object states</li> |
1420 | </ul> |
1421 | |
1422 | </div> |
1423 | |
1424 | <div class="slide"> |
1425 | <h1>Fin</h1> |
1426 | |
1427 | <ul> |
1428 | <li><p>Slides written by:</p> |
1429 | |
1430 | <ul> |
1431 | <li>Chris Prather</li> |
1432 | <li>Stevan Little</li> |
1433 | <li>Robert Boone</li> |
1434 | </ul></li> |
1435 | <li><p>Slides deleted by:</p> |
1436 | |
1437 | <ul> |
1438 | <li>Yuval Kogman</li> |
1439 | </ul></li> |
1440 | <li><p>Slides translated by:</p> |
1441 | |
1442 | <ul> |
1443 | <li>tokuhirom</li> |
1444 | </ul></li> |
1445 | </ul> |
1446 | |
1447 | </div> |
1448 | |
1449 | |
1450 | </div> |
1451 | |
1452 | </body> |
1453 | </html> |