Perl 5.13.2 がもたらした package NAMESPACE BLOCK 構文があたえるもの
開発版の Perl 5.13.2 がリリースされたが、5.13.2 の目玉はなんといっても package NAMESPACE BLOCK 構文だろう。
use 5.13.2; use warnings; package Point { use Moose; has 'x' => (is => 'rw', isa => 'Int'); has 'y' => (is => 'rw', isa => 'Int'); __PACKAGE__->meta->make_immutable; no Moose; };
のように、パッケージを宣言することができるようになった。
この構文は非常に大きい変化をもたらす。
1 ファイルに複数のクラスを書くことが苦でなくなる。package NAME BOCK 構文を利用する場合、BLOCK の中はインデントすることになるため、複数パッケージを1つのファイルにかくことが苦ではなくなってくる。
もう一つは、あのいまわしき "1;" が必要なくなるということ。package NAME BLOCK 構文は true value をかえしているので、通常のクラスを利用する場合には明示的に 1; とかく必要がないようだ(これが明示的な仕様かどうかはまだみてない)。
今迄、ちょっとしたクラスをつくるときに、以下のようにかいていたのも、すっきりするでしょう。
{ package Foo::Bar; }
これを利用して、Tatsumaki の eg/demo.pl を書きなおすと以下のようになる。
今迄の Perl5 コードよりも、見通しがいいんじゃないかとおもう。
#!/usr/bin/perl use 5.13.2; use warnings; use Tatsumaki::Error; use Tatsumaki::Application; use Tatsumaki::HTTPClient; use JSON; package MainHandler { use parent qw(Tatsumaki::Handler); sub get { my $self = shift; $self->write("Hello World"); } } package StreamWriter { use parent qw(Tatsumaki::Handler); __PACKAGE__->asynchronous(1); sub get { my $self = shift; $self->response->content_type('text/plain'); my $try = 0; my $t; $t = AE::timer 0, 0.1, sub { $self->stream_write("Current UNIX time is " . time . "\n"); if ($try++ >= 10) { undef $t; $self->finish; } }; } } package FeedHandler { use parent qw(Tatsumaki::Handler); __PACKAGE__->asynchronous(1); sub get { my($self, $query) = @_; my $client = Tatsumaki::HTTPClient->new; $client->get("http://friendfeed-api.com/v2/feed/$query", $self->async_cb(sub { $self->on_response(@_) })); } sub on_response { my($self, $res) = @_; if ($res->is_error) { Tatsumaki::Error::HTTP->throw(500, $res->status_line); } my $json = JSON::decode_json($res->content); $self->response->content_type('text/html;charset=utf-8'); $self->write("<p>Fetched " . scalar(@{$json->{entries}}) . " entries from API</p>"); for my $entry (@{$json->{entries}}) { $self->write("<li>" . $entry->{body} . "</li>\n"); } $self->finish; } } use File::Basename; my $app = Tatsumaki::Application->new([ '/stream' => 'StreamWriter', '/feed/(\w+)' => 'FeedHandler', '/' => 'MainHandler', ]); if (__FILE__ eq $0) { require Tatsumaki::Server; Tatsumaki::Server->new(port => 9999)->run($app); } else { return $app; }