<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
     xmlns:dc="http://purl.org/dc/elements/1.1/"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xml:lang="ja">
  <channel>
    <title>Casual Track - JPerl Advent Calendar 2009</title>
    <link>http://perl-users.jp/articles/advent-calendar/2009/casual/</link>
    <description>一日一個の CPAN モジュールを紹介します。 </description>
    <item>
      <title>最後の日は最後の一桁を埋めるAlgorithm::CheckDigits</title>
      <link>http://perl-users.jp/articles/advent-calendar/2009/casual/25.html</link>
      <description><![CDATA[<div class="section">
<p>メリクリ！メリクリ！piarraです。</p>

<p>Advent Calendar最後の日は、最後の一桁を埋めるCPANモジュール「Algorithm::CheckDigits」をご紹介します。</p>
<p>このモジュールについて、日本語で紹介されているブログ等を見つけられなかったので、敢えて選んでみました。</p>

<p>こんな経験はありませんか？</p>

<ul>
<li>7桁しかないidを8桁にしたいのだけれど、8桁目を0やランダム値にするのはどうよと思ったとき</li>
<li>なんらかの理由で連番ではないidの生成をしたいとき</li>
<li>JANコードを発行したいのに、何故か12桁しか作れなくって、最後の一桁は自分で作れっていわれても…？なとき</li>
<li>クレジットカードの右端が12mm折れてしまって放置していたら、いつの間にかその破片をなくしてしまったけれど、取り急ぎネットで本を買いたいのに、クレジットカードの最後の一桁がどうしても分からないとき</li>
</ul>

<p>そんなときは、Algorithm::CheckDigitsの出番です。</p>
</div>
<div class="section">
<h3>チェックデジットとは</h3>
<p>さて、「CheckDegit(チェックデジット)」という言葉に馴染みのない方もいらっしゃると思うので、まずは基本的なお話から。</p>

<p>Wikipediaによると、</p>
<pre>
「チェックディジット（check digit, 検査数字）とは、
符号の入力誤りなどを検出するために元の符号に付加される数字のこと。」
</pre>
<p>とされています。</p>
<p>馴染みの深いところでは、バーコードなどで読み取りミスを防ぐために、最後の一桁にチェックデジットを付与して、データを誤って読み取ってしまうことを防いでいます。</p>

<p>例えば、「初めてのPerl」のISBN"978-4-87311-126-1"の最後の"1"はチェックデジットです。</p>
</div>
<div class="section">
<h3>計算してみる</h3>
<p>まずは実際に上のISBNコードのチェックデジットを計算してみます。</p>
<p>ISBNコードやJANコードは、「モジュラス10 ウェイト3・1」というアルゴリズムで算出されます。</p>
<p>このアルゴリズムでは、"左から奇数桁の数字の合計"と、"偶数桁の数字の合計を3倍にしたもの"を加え、10からその和の下一桁の数字を引いてチェックデジットを求めます。</p>
<pre>
(9 + 8 + 8 + 3 + 1 + 2) + (7 + 4 + 7 + 1 + 1 + 6) * 3 = 109 ・・・下一桁は9
10 - 9 = 1 ・・・ この1がチェックデジット
</pre>

<p>確かに計算結果と実際の値とが一致しました。比較的簡単な計算のアルゴリズムですね。</p>
</div>
<div class="section">
<h3>Perl登場｜・ω・)ノ</h3>
<p>Perlの苦手な方はチェックデジットくらい暗算をするみたいですが、</p>
<p>小学校を卒業した賢いCasual Perlerの皆さんは当然Perlを使いますよね。</p>

<p>というわけで、Perlで簡単にチェックデジットを付与し、あるいは検証するモジュールの紹介です。</p>
</div>
<div class="section">
<h3>Algorithm::CheckDegits</h3>
<pre>
use Algorithm::CheckDigits;

my $isbn13 = CheckDigits('ISBN13');
if ($isbn13->is_valid('978-4-87311-126-1')) {
    # OK
}

my $lp_isbn = $isbn13->complete('978-4-87311-126');
print $lp_isbn . "\n";
</pre>

<p>上の通り、CheckDigits()関数にて付与したいチェックデジットの種類を指定します。</p>
<p>ここでは、13桁の新ISBNコードを使っていますので、"ISBN13"という指定をしています。</p>
<p>他には、クレジットカードの"VISA"や"AMEX"、"DINERS"、Amazon等でおなじみの"EAN"(JANもこれと同じ)などが指定できます。</p>
<p>指定できるアルゴリズム名の一覧は、</p>
<pre>
my @ml = Algorithm::CheckDigits->method_list();
</pre>
<p>で取得できます。</p>
<p>ちなみに、m10_005などという命名がなされていますが、それは必ずしも名前通りモジュラス10ウェイト5という意味ではないようですので注意が必要です。</p>
<p>※実際にはm10_004がモジュラス10ウェイト3.1に該当、m10-005がモジュラス10ウェイト4.9に該当など</p>

<p>実際のアルゴリズムを確認したい場合は、以下のようにperldocを参照するか、ソースをご覧ください。</p>
<pre>
perldoc Algorithm::CheckDigits::M10_005
</pre>
</div>
<div class="section">
<h3>様々な用途</h3>
<p>チェックデジットというのは、数値の検証に用いるのが本来の用途だと思いますが、それ以外にも私自身は以下のような用途で使っています。</p>
<ul>
<li>IDの桁数を揃えたい場合で、桁数に余裕があり、かつ連番やゼロを避けたいとき(00001,00002,00003...よりも00016,00025,00034...とすることで連番を避けた様に見える)</li>
<li>JANコードやISBN等を保存する際、1文字分の容量を節約したいとき</li>
<li>彼女の誕生日の下一桁を忘れたとき</li>
</ul>
</div>
<div class="section">
<h3>クリスマスチェックデジット</h3>
<p>チェックデジットでクリスマスがcompleteできるか遊んでみました。</p>
<pre>
my $christmas = CheckDigits('EAN');
print $christmas->complete('2009122'); # 結果はご自身でご確認ください:)
</pre>
</div>
<div class="section">
<h3>最後に</h3>
<p>さて、25日間にわたってお楽しみいただいたJperl Advent Calendar - Casual Trackも今日で最後となりました。</p>
<p>毎日欠かさずチェックいただいたcasual perlerやperl hackerの皆さんありがとうございました。</p>
<p>そして、今日まで途切れることなくバトンをつないで頂いたcasual perlerの皆様お疲れ様でした。</p>

<p>また来年のAdvent Calendarに参加できることを楽しみにしています。</p>
<p>それでは、皆様良いお年を。</p>
</div>
<div class="section">
<h3>参考</h3>
<ul>
<li><a href="http://search.cpan.org/~mamawe/Algorithm-CheckDigits-0.53/">http://search.cpan.org/~mamawe/Algorithm-CheckDigits-0.53/</a></li>
<li><a href="http://ja.wikipedia.org/wiki/%E3%83%81%E3%82%A7%E3%83%83%E3%82%AF%E3%83%87%E3%82%A3%E3%82%B8%E3%83%83%E3%83%88">http://ja.wikipedia.org/wiki/%E3%83%81%E3%82%A7%E3%83%83%E3%82%AF%E3%83%87%E3%82%A3%E3%82%B8%E3%83%83%E3%83%88</a></li>
<li><a href="http://ja.wikipedia.org/wiki/JAN%E3%82%B3%E3%83%BC%E3%83%89">http://ja.wikipedia.org/wiki/JAN%E3%82%B3%E3%83%BC%E3%83%89</a></li>
</ul>
</div>
<div class="section">
<h3>Special Thanks</h3>
<p>id:kimury</p>

</div>
]]></description>
      <dc:creator>piarra</dc:creator>
      <pubDate>Fri, 25 Dec 2009 12:24:15 GMT</pubDate>
      <category></category>
    </item>
    <item>
      <title>Image::Imlib2でアイコンをクリスマス仕様に</title>
      <link>http://perl-users.jp/articles/advent-calendar/2009/casual/24.html</link>
      <description><![CDATA[<div class="section">
<p>ハッピーメリークリスマス！aomushi510です。好きなお寿司のネタはサーモンです！</p>

<p>今日はクリスマスイブということで、Image::Imlib2を使って簡単にアイコンをクリスマス仕様にしちゃいましょう！</p>
<p>Perlで画像加工をするときに使うモジュールは、Image::Imlib2の他にもImage::MagickやImager、GD::Imageなどがあります。</p>
<p><a href="http://yusukebe.com/tech/archives/20070526/011710.html">yusukebeさんのエントリ</a>では、Image::Imlib2が超絶速いそうです。Image::Imlib2すごい！ってことで早速はじめましょう。</p>
</div>
<div class="section">
<h3>はじめに</h3>
<p>まずはImage::Imlib2をインストールしましょう。</p>
<p>インストールをする前に、Cのライブラリと使いたい画像形式のライブラリを入れておきましょう。</p>
<p>今回はjpegとpngを使いたいと思います。</p>
<pre>
$ port install libpng
$ port install imlib2
</pre>

<p>ではImage::Imlib2をインストールします。簡単ですね！</p>
<pre>
cpan> install Image::Imlib2
</pre>
</div>
<div class="section">
<h3>画像の読み込み、書き出し</h3>
<p>インストールできたら、画像を読み込んだり書き出したりしてみましょう。</p>
<p>face.jpgを読み込んで、face2.jpgに書き出してみます。</p>
<pre>
#!/usr/bin/perl

use strict;
use warnings;
use Image::Imlib2;

my $dir = '/path/to/image';

my $image = Image::Imlib2->load("$dir/face.jpg");
$image->save("$dir/face2.jpg");
</pre>

<p>できた画像</p>
<p><a href="http://azu.sh/jperl_advent_calendar_2009/image/face2.jpg"><img src="http://azu.sh/jperl_advent_calendar_2009/image/face2.jpg" alt="http://azu.sh/jperl_advent_calendar_2009/image/face2.jpg" /></a></p>

</div>
<div class="section">
<h3>画像の合成</h3>
<p>これであなたもImage::Imlib2を使うことができました！が、肝心のアイコンがさみしいです＞＜</p>
<p>クリスマスということで、サンタ帽をかぶってみましょう。</p>

<p><a href="http://azu.sh/jperl_advent_calendar_2009/image/santa_hat.png"><img src="http://azu.sh/jperl_advent_calendar_2009/image/santa_hat.png" alt="http://azu.sh/jperl_advent_calendar_2009/image/santa_hat.png" /></a></p>
<p>このようなサンタ帽画像を用意します。それでは合成してみましょう。</p>
<pre>
#!/usr/bin/perl

use strict;
use warnings;
use Image::Imlib2;

my $dir = '/path/to/image';

my $image = Image::Imlib2->load("$dir/face.jpg");
$image->set_quality(100);
my $santa_hat = Image::Imlib2->load("$dir/santa_hat.png");
$image->blend($santa_hat, 1, 0, 0, 300, 300, 0, 0, 300, 300);

$image->save("$dir/with_santa_hat.png");
</pre>

<p>できた画像</p>
<p><a href="http://azu.sh/jperl_advent_calendar_2009/image/with_santa_hat.png"><img src="http://azu.sh/jperl_advent_calendar_2009/image/with_santa_hat.png" alt="http://azu.sh/jperl_advent_calendar_2009/image/with_santa_hat.png" /></a></p>
<p>サンタ帽をかぶることができました！簡単ですね！</p>

</div>
<div class="section">
<h3>画像を作成する</h3>
<p>サンタ帽をかぶってクリスマスっぽくなりました。もうひといき、今度は星画像を作ってみましょう。</p>
<p>Image::Imlib2::Polygonというモジュールを使って多角形を作ります。</p>
<p>星形は正五角形の頂点を結ぶので、先にShape::RegularPolygonを利用して正五角形の頂点を取得しておきます。</p>
<p>そのあと1つ飛びに頂点を描き、まさに手書きで星を書くときのように描いていきます。</p>
<p>これだけでは中の正五角形が塗られないので、中身も後から塗って星形の完成です。</p>

<pre>
#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;
use Image::Imlib2;
use Shape::RegularPolygon;

my $dir = '/path/to/image';

my $image = Image::Imlib2->new_transparent(100, 100);
$image->set_colour(255, 255, 0, 255);

my $points = &get_points(50);
my $poly = Image::Imlib2::Polygon->new();

for my $point (@$points) {
    $poly->add_point($point->{x}, $point->{y});
}
$poly->fill();

$image->draw_polygon($poly, 1); 
$image->fill(50,50);
$image->save("$dir/star.png");


sub get_points {
    my $center = shift;

    my $polygon = new Shape::RegularPolygon;
    $polygon->center($center, $center);
    $polygon->sides(5);
    $polygon->radius(50);
    my @points = $polygon->points;

    return [$points[0], $points[2], $points[4], $points[1], $points[3], $points[0]];
}
</pre>
<p>できた画像</p>
<p><a href="http://azu.sh/jperl_advent_calendar_2009/image/star.png"><img src="http://azu.sh/jperl_advent_calendar_2009/image/star.png" alt="http://azu.sh/jperl_advent_calendar_2009/image/star.png" /></a></p>


<p>できた画像を合成します。</p>
<p>create_rotate_imageで画像を回転させて貼り付けます。</p>

<pre>
#!/usr/bin/perl

use strict;
use warnings;
use Image::Imlib2;

my $dir = '/path/to/image';

my $image = Image::Imlib2->load("$dir/with_santa_hat.png");
$image->set_quality(100);
my $star = Image::Imlib2->load("$dir/star.png");
$image->blend($star, 1, 0, 0, 100, 100, 0, 200, 100, 100);

my $rotated = $star->create_rotated_image(30 / 360 * 3.141519*2);
$image->blend($rotated, 1, 0, 0, 150, 150, 210, 80, 100, 100);

$image->save("$dir/with_star.png");
</pre>
<p>できた画像</p>
<p><a href="http://azu.sh/jperl_advent_calendar_2009/image/with_star.png"><img src="http://azu.sh/jperl_advent_calendar_2009/image/with_star.png" alt="http://azu.sh/jperl_advent_calendar_2009/image/with_star.png" /></a></p>
<p>できました！これでアイコンがにぎやかになりましたね！</p>

</div>
<div class="section">
<h3>まとめ</h3>
<p>Image::Imlib2を使うと簡単に画像を加工することができます。ちょっとした画像編集にPerlを使ってみるのはいかがですか？</p>

<p>明日はAdvent Calendarの大トリ、piarraさんです。楽しみですね！</p>

</div>
<div class="section">
<h3>参考</h3>
<ul>
<li><a href="http://search.cpan.org/~lbrocard/Image-Imlib2-2.03/lib/Image/Imlib2.pm">http://search.cpan.org/~lbrocard/Image-Imlib2-2.03/lib/Image/Imlib2.pm</a></li>
<li><a href="http://yusukebe.com/tech/archives/20070526/011710.html">http://yusukebe.com/tech/archives/20070526/011710.html</a></li>
<li><a href="http://it.kndb.jp/entry/show/id/2572">http://it.kndb.jp/entry/show/id/2572</a></li>
<li><a href="http://rakasaka.fc2web.com/delphi/star.html">http://rakasaka.fc2web.com/delphi/star.html</a></li>
</ul>
</div>
]]></description>
      <dc:creator>aomushi510</dc:creator>
      <pubDate>Thu, 24 Dec 2009 00:00:00 GMT</pubDate>
      <category></category>
    </item>
    <item>
      <title>Mojolicious Plackup!</title>
      <link>http://perl-users.jp/articles/advent-calendar/2009/casual/23.html</link>
      <description><![CDATA[<div class="section">
<p>Hi, perl-users.</p>

<p>The past few days, Although I couldn't decide what to write day 23, fortunately, <a href="http://twitter.com/kraih/status/6722965569">sri</a> added native PSGI support to Mojolicious at 12/16/2009.  I decided to write this article of this feature.</p>


<p>So, this year, the most interesting thing in YAPC::Asia 2009 is PSGI/Plack from Miyagawa-san. PSGI is Perl Web Server Gateway Interface Specfication, and Plack is PSGI reference implementation and utilities(I think you know it). For details, go to <a href="http://plcackperl.org">plackperl.org</a> and Googling around it if you want.</p>


<p>First of all, You install Mojo and Plack. I think it would be better to use local::lib. As for local::lib, Please refer to <a href="http://perl-users.jp/articles/advent-calendar/2009/casual/02.html">day 2</a> by otsune-san. Mojo installation is very easy. Doesn't have any dependency other than Perl 5.8.1. </p>

<p>A word of caution: Do not use Mojo(0.999914) on CPAN in this article. You should install Mojo(0.999915) from <a href="http://github.com/kraih/mojo">github</a>. Only github includes PSGI feature. Not includes it on CPAN now. Sorry, I don't expalin installation process in detail here.</p>


<p>Once those installs are done, generate a mojolicious application. Mojo has a helper script that creates all the working files that you need get started in the directory.</p>
<pre>
$ ./extlib/bin/mojolicious generate app Centipede
</pre>
<pre>
$ ls -al
drwxr-xr-x  8 kaz kaz 4096 2009-12-20 22:02 centipede/ # Mojo Application
drwxr-xr-x  5 kaz kaz 4096 2009-12-20 21:45 extlib/    # libraries
</pre>


<p>Once you have generated your application, prepare for the ".psgi". Interestingly, Mojo has a ".psgi" generator.</p>
<pre>
$ mv centipede/script/
$ ./centipede generate psgi
</pre>
<p>centipede.psgi</p>
<pre>
use FindBin;

use lib "$FindBin::Bin/lib";
use lib "$FindBin::Bin/../lib";

use Mojo::Server::PSGI;

my $psgi = Mojo::Server::PSGI->new(app_class => 'Centipede');
my $app  = sub { $psgi->run(@_) };
</pre>


<p>Let's plackup!</p>
<pre>
$ perl -I./centipede/lib ./extlib/bin/plackup -app ./centipede/centipede.psgi
</pre>
<p>Now we have our standalone server running on port 5000 so browsing:<br/> <a href="http://localhost:5000">http://localhost:5000</a><br /> And will see a welcome message from Mojolicious.</p>


<p>Specifically, I think Mojo::Server::PSGI is NOT server, enables Mojo applications to adapt PSGI protocole like CGI::PSGI.</p>
<pre>

 .----------------.
 |   Mojolicious  |
 '----------------'
         |
    .---------.
    |   Mojo  |
    '---------'
         |
.----------------------.
|  Mojo::Server::PSGI  |
'----------------------'
         |
    .---------.
    |  Plack  |
    '---------'
         |
    .----------.
    |  Server  |
    '----------'

</pre>


<p>Mojo already supports most server environment. Although I think PSGI might not be direct benefit immediately,  It is going to get a fast server and useful middlewares near future. I'm looking forward to it.</p>


<p>My English Sux. FIXME.</p>
<p>Next day 24 is aomushi510-san. Don't miss it!</p>

<p>#mojoの人にも読んでもらえらたらなーと思い英語が得意なわけでもないのに英語で書いてみました。英語読みたくない方や間違いだらけで恥ずかしくて読んでいられないというかたはブログに日本語で書くつもりなのでそちらをどうぞ:)</p>

</div>
]]></description>
      <dc:creator>ka2u</dc:creator>
      <pubDate>Wed, 23 Dec 2009 14:57:01 GMT</pubDate>
      <category></category>
    </item>
    <item>
      <title>BackPANで失せ物を探す</title>
      <link>http://perl-users.jp/articles/advent-calendar/2009/casual/22.html</link>
      <description><![CDATA[<p>今年も残るところ10日をきりました。皆様如何お過ごしでしょうか。今日は<strong>Acme話を自重する</strong>つもりのmakamaka_at_donzokoでございます。</p>

<p>さて、年の瀬ともなりますと大掃除なんかになりまして、無くしたと思っていたものが見つかったとか、あると思っていたものが見当たらない、なんてことがよくあります。見つかる方は良いのですが、気がついたら無くなってた、というのは困ります。</p>

<p>という強引な前振りですが、search.cpan.orgでモジュールを探していて、「あれ？　確か前はあったはずなのに……」なんて経験、ありませんか？</p>

<p>そう、例えば、今年の初めにはCPANにあったAcme::BabyEaterがなくなってたり、2003年には確かにあったAcme::ManekiNekoが見当たらなくなったり（と思ったら後にひょっこり帰ってきましたが）という具合にですね。</p>

<pre><code>% cpan Acme::BabyEater
(中略)
Warning: Cannot install Acme::BabyEater, don't know what it is.
Try the command

    i /Acme::BabyEater/
</code></pre>

<p>むむむ……　search.cpan.orgで調べるてみても<a href="http://search.cpan.org/dist/Acme-BabyEater/">やっぱり見あたらない</a>。</p>

<p>ディストリビューションがまるまる無くなってしまうのも困りものですが、そうでなくても結構やっかいなケースがあります。</p>

<p>例えば、あるモジュールのバージョンが上がったところ、インストールできなくなったり、今まで動いていたものとの互換性がなくなったり（すいません私、前科あります）ということが、ままあります。</p>

<p>特に古いバージョンのPerl（5.005系や5.6系）で動いていたモジュールがある時点で対応しなくなった上に、以前のモジュールがCPANから削除されていたりすると、まあ大変！（え？　Perlのバージョン上げろと？　色々大人の事情でダメな場合がありますので……）</p>

<p>このように、あなたがお探しのモジュールがCPANから消えてしまった時は、BackPANに出かけましょう！</p>

<hr />

<p><a href="http://backpan.perl.org/">BackPAN</a> "A Complete History of CPAN"は、PAUSE(Perl Authors Upload Server)にアップされたファイルを全て保存しています。そしてPAUSEからモジュールを削除しようとも、BackPANからは削除されません。ですので、BackPANはCPANの「歴史」であり、もはや顧みられなくなった多くのモジュールが静かに（？）眠っているのです。BackPANをCPAN墓場と呼ぶ人もいます。<a href="http://www.slideshare.net/brian_d_foy/backpan-archeology-presentation" title="the bone yard of CPAN">例1</a> 
<a href="http://search.cpan.org/dist/Module-ThirdParty/" title="the BackPAN graveyard">例2</a></p>

<p>さて、BackPANに行けば、なんでもそろっています。行ってみましょう。</p>

<p><a href="http://backpan.perl.org/authors/id/">authors/id/....</a>……CPAN ID別にディレクトリが分かれているので、ちょっとモジュールを探すのが面倒そうですね。</p>

<p>そこで<a href="http://search.cpan.org/dist/Parse-BACKPAN-Packages/">Parse::BACKPAN::Packages</a>の登場です。このモジュールは、BackPANのインデックスデータ<a href="http://www.astray.com/tmp/backpan.txt.gz">http://www.astray.com/tmp/backpan.txt.gz</a>を利用して、ディストリビューション名や作者からBackPAN上のアドレスを教えてくれます。</p>

<pre><code>#!/usr/bin/perl

use strict;
use warnings;
use Parse::BACKPAN::Packages;

my $p = Parse::BACKPAN::Packages-&gt;new();

my $distname = $ARGV[0] or die "Distribution name?";
my $check_version;

if ( $distname =~ /^(.+?)-([_.\d]+)$/ ) { # バージョンまで指定
    $check_version = $2;
    $distname = $1;
}
else { # P::B::PはFoo-Bar形式で受け付けるので、Foo::Bar形式にも対応
    $distname =~ s/::/-/g;
}

# リストは日付の古い順
my @dists = $p-&gt;distributions( $distname ) or die "Can't find $distname";
my $file;

if ( defined $check_version ) {
    for my $dist ( @dists ) {
        if ( $dist-&gt;version == $check_version ) {
            $file = $p-&gt;file( $dist-&gt;prefix );
            last;
        }
    }
}
else {
    $file = $p-&gt;file( $dists[ -1 ]-&gt;prefix );
}

die "$distname was found, but not version $check_version." unless $file;

print $file-&gt;url, "\n";
</code></pre>

<p>backpan_url.plという名前をつけて</p>

<pre><code>% perl backpan_url.pl Acme::BabyEater
</code></pre>

<p>とやってみましょう。</p>

<p><code>http://backpan.cpan.org/authors/id/Z/ZO/ZOFFIX/Acme-BabyEater-0.04.tar.gz</code>が出力されました（<a href="http://backpan.cpan.org/">http://backpan.cpan.org/</a>ですが問題ありません）。</p>

<p>最初はインデックスデータを取りに行くため、初期化にかなり時間がかかるかもしれませんが、一度データを取得すると、1時間キャッシュされます。</p>

<p>上記のサンプルでは該当するディストリビューションの最新版を返しますが、<code>Acme-Manekineko-0.01</code>のような形式にすれば、バージョン0.01を探します。</p>

<hr />

<p>さて、これでモジュールは簡単に手に入るようになりました。後はファイルを展開して<code>cpan .</code>とでもすれば良いでしょう。でもどうせなら、コマンド一発でインストールしたいです。</p>

<p>cpanコマンドからBackPANサイトにアクセスしてうまいことやってくれないかなあ、と考えたのですが、これはなかなか難しいようです（ローカルに自分の用のCPANサイトを作る方法がありますが、そこまで大掛かりにしたくない）。色々検討した結果、<a href="http://search.cpan.org/dist/CPAN-Inject/">CPAN::Inject</a>を使うことにします。</p>

<pre><code>use strict;
use warnings;
use CPAN::Shell;
use CPAN::Inject;

my $cpan_inject = CPAN::Inject-&gt;new(
    sources =&gt; "$CPAN_HOME/sources",
    author  =&gt; 'MAKAMAKA',
);

my $install_path = $cpan_inject-&gt;add( file =&gt; 'path/Not-In-CPAN-1.00.tar.gz' );
</code></pre>

<p>こうすると<code>$CPAN_HOME/sources</code>下の適切な位置（例えば /home/makamaka/.cpan/sources/authors/id/M/MA/MAKAMAKA）にNot-In-CPAN-1.00.tar.gzをコピーしてCHECKSUMを生成してくれます（<code>new</code>の代わりに<code>from_cpan_config</code>を使えばCPAN::Configから自動的に<code>$CPAN_HOME/sources</code>を設定）。</p>

<p>ここまでくると、後はCPAN::Shellを使ってinstallも簡単。</p>

<pre><code>CPAN::Shell-&gt;install( $install_path );
</code></pre>

<p>うまくいけばいつものようにインストールされます。先に載せたbackpan_url.plでURLを取得、ファイルをGETして上記のサンプルコードで適宜設定してしまえば、一連の作業を自動化できますね。</p>

<p>というわけで、上記の処理を簡単に行うために<a href="http://github.com/makamaka/perl-backpan-downloader">BackPAN::Downloader</a>を作ってみました。</p>

<pre><code>package BackPAN::Downloader;

use Mouse;
use Parse::BACKPAN::Packages;
use CPAN::Inject;
use LWP::UserAgent;
use CPAN::Debug;
use CPAN::Shell;
use Path::Class;
use Try::Tiny;
use Cwd;
use Data::Dumper;

our $VERSION = '0.01';

has distfile =&gt; ( is =&gt; 'rw', isa =&gt; 'Parse::BACKPAN::Packages::Distribution|Undef' );

has filedata =&gt; ( is =&gt; 'rw', isa =&gt; 'Parse::BACKPAN::Packages::File|Undef' );

has dist_is_found =&gt; ( is =&gt; 'rw', isa =&gt; 'Bool' );

has temp_dir =&gt; ( is =&gt; 'rw', isa =&gt; 'Str', default =&gt; './' );

has ua =&gt; ( is =&gt; 'rw', isa =&gt; 'LWP::UserAgent', default =&gt; sub { LWP::UserAgent-&gt;new     } );

has error =&gt; ( is =&gt; 'rw', isa =&gt; 'Str|Undef' );

no Mouse;


sub reset {
    my ( $self ) = @_;
    $self-&gt;dist_is_found( 0 );
    $self-&gt;distfile( undef );
    $self-&gt;filedata( undef );
    $self-&gt;error( undef );
}


sub lookup {
    my ( $self, $distname ) = @_;
    my $check_version;

    $self-&gt;reset;

    if ( $distname =~ /^(.+?)-([_.\d]+)$/ ) { # バージョン指定なので正式名称
        $check_version = $2;
        $distname = $1;
    }
    else {
        $distname =~ s/::/-/g; # Foo-BarだけでなくFoo::Barでも検索できるように
    }

    my $p = Parse::BACKPAN::Packages-&gt;new();

    # リストは日付の古い順
    my @dists = $p-&gt;distributions( $distname );
    my $found;

    if ( defined $check_version ) {
        for my $dist ( @dists ) {
            if ( $dist-&gt;version == $check_version ) {
                $found = $dist;
                last;
            }
        }
    }
    else {
        $found = $dists[ -1 ] if ( @dists );
    }

    if ( $found ) {
        $self-&gt;distfile( $found );
        $self-&gt;filedata( $p-&gt;file( $found-&gt;prefix ) );
        $self-&gt;dist_is_found( 1 );
    }
    else {
        $self-&gt;error( "Can't find $distname." );
    }

    return $found;
}


sub download {
    my ( $self ) = @_;

    unless ( $self-&gt;dist_is_found ) {
        $self-&gt;error('donwload() must be called after the dist file was found.');
        return;
    }

    my $url  = $self-&gt;filedata-&gt;url;
    my $file = Path::Class::File-&gt;new( $self-&gt;temp_dir, $self-&gt;distfile-&gt;filename );

    return 1 if ( -s $file );

    my $ua   = $self-&gt;ua;
    my $res  = $ua-&gt;get( $url );

    if ( $res-&gt;is_success ) {
        my $fh = $file-&gt;openw();
        unless ( $fh ) {
            $self-&gt;error( "Can't open file." );
            return;
        }
        print $fh $res-&gt;content;
    }
    else {
        $self-&gt;error( "Can't download, status line is " . $res-&gt;status_line );
        return;
    }
}


sub install {
    my ( $self, %opts ) = @_;

    unless ( $self-&gt;dist_is_found ) {
        $self-&gt;error('donwload() must be called after the dist file was found.');
        return;
    }

    my $distfile = $self-&gt;distfile;
    my $cpan_inject = CPAN::Inject-&gt;from_cpan_config( author =&gt; $distfile-&gt;cpanid );

    my $installed;
    my $file = Path::Class::File-&gt;new( $self-&gt;temp_dir, $distfile-&gt;filename );
    my $cwd  = getcwd;

    try {
        my $inst_path = $cpan_inject-&gt;add( file =&gt; $file );
        CPAN::Shell-&gt;install( $inst_path );
        $installed = 1;
    } catch {
        $self-&gt;error( @_ );
    };

    chdir( $cwd );

    if ( $installed and $opts{ delete_saved_file } ) {
        unlink($file) or Carp::carp("Can't delete saved file $file. $!");
    }

    return $installed;
}

#------- backpan_inst.pl
package main;

use strict;
use warnings;

@ARGV or die "Distribution name?";

my $backpan  = BackPAN::Downloader-&gt;new( temp_dir =&gt; './tmp' );

for my $distname ( @ARGV ) {

    $backpan-&gt;reset;

    unless ( $backpan-&gt;lookup( $distname ) ) {
        printf( "%s was not found.\n", $distname );
        next;
    }

    printf( "Found %s in %s\n", $distname, $backpan-&gt;filedata-&gt;url );

    $backpan-&gt;download() or die sprintf("Can't download. (%s)", $backpan-&gt;error);
    $backpan-&gt;install( delete_saved_file =&gt; 1 )  or die "Can't install, " . $backpan-&gt;error;
}
</code></pre>

<p>さあ、試してみましょう。ダウンロードしたファイルを一時的に保存するtmpディレクトリを作成して</p>

<pre><code>% perl backpan_inst.pl Acme::BabyEater
</code></pre>

<p>例によってデータ取得に時間がかかるかもしれませんが、</p>

<pre><code>Found Acme::BabyEater in http://backpan.cpan.org/authors/id/Z/ZO/ZOFFIX/Acme-BabyEater-0.04.tar.gz
Going to read '/home/makamaka/.cpan/Metadata'
  Database was generated on Sat, 19 Dec 2009 01:30:46 GMT
CPAN: YAML loaded ok (v0.68)
Running make for Z/ZO/ZOFFIX/Acme-BabyEater-0.04.tar.gz
Checksum for /home/makamaka/.cpan/sources/authors/id/Z/ZO/ZOFFIX/Acme-BabyEater-0.04.tar.gz ok
(..skip..)
  ZOFFIX/Acme-BabyEater-0.04.tar.gz
  ./Build install  -- OK
</code></pre>

<p>うまくいきました。上のサンプルは<a href="http://github.com/makamaka/perl-backpan-downloader">http://github.com/makamaka/perl-backpan-downloader</a>にあります。</p>

<p>そうそう、副次効果がありました。Acme::Tinyのように、<code>cpan</code>コマンドからインストールするためにはCPAN IDとバージョンを調べて</p>

<pre><code>cpan DMUEY/Acme-Tiny-0.4.tar.gz
</code></pre>

<p>しないといけないディストリビューションでも、</p>

<pre><code>% perl backpan_inst.pl Acme::Tiny
</code></pre>

<p>で、一発インストール可能です。素晴らしい！　これでインデックス化されないAcme7ディストリも怖くない！</p>

<hr />

<p>それから、BackPANの他にも、最近はschwern氏によってCPANの歴史をgithubに移そうという試みがされています（<a href="http://github.com/gitpan/">gitpan</a>）。</p>

<p><br /><br />さて、それでは最後に、冒頭で取り上げたAcme::ManekiNekoについてのちょっといい話をいたしましょう。</p>

<p>2003年の後、作者はこのモジュールをCPANから削除します。ところが、このモジュールを愛する人たちがいることを知ります。しかし、時既に遅し。作者はコードを失っていました。</p>

<p>おお、なんてことでしょう！</p>

<p>作者は自分を責めます。</p>

<p>しかし！</p>

<p>そう、BackPANがあったのです！</p>

<p>こうして2008年に再びAcme::ManekiNekoはCPANに復活するのでありました。クリスマスの季節に相応しい素敵な物語ですね。</p>

<p>明日はka2uさんです。ではでは～</p>

<hr />

<p>参考：</p>

<p>BackPANについて</p>

<ol>
<li><a href="http://www.slideshare.net/brian_d_foy/indexing-backpan">Indexing Backpan</a></li>
<li><a href="http://www.slideshare.net/brian_d_foy/backpan-archeology-presentation">Backpan  Archeology</a></li>
<li><a href="http://www.slideshare.net/brian_d_foy/making-my-own-cpan">Making Your Own CPAN</a></li>
<li><a href="http://backpan.cpan.org/authors/id/H/HF/HFB/grok-cpan.pdf">Grokking The CPAN</a></li>
</ol>

<p>ローカルCPAN関連（DarkPAN面白そう）</p>

<ol>
<li><a href="http://www.naney.org/diki/d/2006-02-b.html#2006-02-12-CPAN-Mini-Inject">野良パッケージと依存PerlモジュールのインストールセットをCPAN::Mini::Injectで</a></li>
<li><a href="http://log.perl.org/2005/09/create_your_own.html">Create your own "BackPAN"</a></li>
<li><a href="http://www.perlmonks.org/?node_id=722831">A preview of DPAN</a></li>
<li><a href="http://use.perl.org/~brian_d_foy/journal/37375">Cataloging BackPAN: MiniCPAN done in 9 hours</a></li>
</ol>

<p>gitpanについて</p>

<ol>
<li><a href="http://use.perl.org/~schwern/journal/39972">gitPAN</a></li>
</ol>

<p>Acme::ManekiNekoについて</p>

<ol>
<li><a href="http://search.cpan.org/~gmccar/Acme-ManekiNeko-0.02/ManekiNeko.pm#HISTORY">Acme::ManekiNeko/HISTORY</a></li>
<li><a href="http://www.runme.org/project/+AcmeManekiNeko/">Acme::ManekiNekoの画像</a></li>
<li><a href="http://www.hyuki.com/yukiwiki/wiki.cgi?Acme%3A%3AManekiNeko">招き猫モジュール</a></li>
<li><a href="http://www.donzoko.net/doc/perlmod/subarasiki.html">素晴らしきPerlモジュールの世界</a></li>
</ol>

<p>その他</p>

<ol>
<li><a href="http://kawa.at.webry.info/200911/article_8.html">Mac OS X 10.6（Snow Leopard）にPerl 5.005をインストールする</a>
↑ここでmiyagawaさんがコメントしている<a href="http://cp5.5.3an.barnyard.co.uk/">http://cp5.5.3an.barnyard.co.uk/</a>、<a href="http://cp5.6.2an.barnyard.co.uk/">http://cp5.6.2an.barnyard.co.uk/</a>などは初めて知りました。</li>
</ol>
]]></description>
      <dc:creator>makamaka_at_donzoko</dc:creator>
      <pubDate>Mon, 21 Dec 2009 23:00:00 GMT</pubDate>
      <category></category>
    </item>
    <item>
      <title>Coroを使って並行処理</title>
      <link>http://perl-users.jp/articles/advent-calendar/2009/casual/21.html</link>
      <description><![CDATA[<div class="section">
<p>こんにちわ。<a href="http://groups.google.co.jp/group/sheaf-category-and-topos">『層・圏・トポス』読者の会</a>からの刺客、<a href="http://d.hatena.ne.jp/hiratara/">id:hiratara</a>です。</p>

<p>「並行処理」って言葉はなんだか魅力的ですよね！ そこで、今日は<a href="http://search.cpan.org/~mlehmann/Coro/">Coro</a>を使った並行処理を紹介します。なお、<a href="http://search.cpan.org/~mlehmann/Coro/">Coro</a>はコアモジュールではありませんので、使ってみたい場合にはCPANからインストールして下さい。</p>
</div>
<div class="section">
<h3>スレッドを作る</h3>

<p>Coroでは、asyncによって新しいスレッドを作ることができます。ただし、asyncでスレッドを作っても、何もしなければ他のスレッドに勝手に処理が移ることはありません。asyncで作成した別のスレッドに制御を移すには、明示的な操作が必要となります。ここではcedeを使って、asyncブロックへ処理を移しましょう。</p>

<pre>
use strict;
use warnings;
use Coro;

async {
    print "Another thread\n";
};

print "main thread\n";
cede;
print "main thread, again.\n";

__END__

[実行結果]
main thread
Another thread
main thread, again.
</pre>

<p>cedeを呼んだタイミングでasyncブロックに制御が移り、ブロックを抜けた後にcedeの次の行に制御が戻って来ています。</p>
</div>
<div class="section">
<h3>並行処理させる</h3>

<p>次に、いくつかのスレッドを並行処理をさせてみましょう。Coroでの並行処理は、あるスレッドの待ち時間に他のスレッドが動いてくれる、ってのがミソとなります。ここではCoro::Timer::sleepを使ってその原理を見てみます。</p>

<pre>
use strict;
use warnings;
use Coro;
use Coro::Timer;

my @coros;
for my $sec (1 .. 3){
    push @coros, async {
        print "wait $sec sec.\n";
        Coro::Timer::sleep $sec;
        print "after $sec sec.\n";
    } ;
}
$_->join for @coros;

__END__

[実行結果]
wait 1 sec.
wait 2 sec.
wait 3 sec.
after 1 sec.
after 2 sec.
after 3 sec.
</pre>

<p>1秒かかる処理、2秒かかる処理、3秒かかる処理を実行してますので、並行処理でなければ6秒かかるはずです。しかし、Coro::Timer::sleepを使っているため、これらのスレッドは並行動作し、このプログラムは3秒で終了します。</p>
</div>
<div class="section">
<h3>実例: URLのダウンロード</h3>
<p>sleepするだけでは面白くないので、もう少し具体的な例を見ておきましょう。Coro::LWPを使うと、LWPがCoroを使ってなるべくブロックしないように動くようになります。言い換えると、LWPが、待ち時間になると他のスレッドに処理を移すことで並行動作するようになるということです。</p>

<pre>
use strict;
use warnings;
use Coro;
use Coro::LWP;
use LWP::UserAgent;

my @coros;
for my $url (
    'http://d.hatena.ne.jp/hiratara/',
    'http://www.google.co.jp/',
    'http://www.yahoo.co.jp/',
){
    push @coros, async {
        my $ua = LWP::UserAgent->new;
        print "load $url\n";
        my $res = $ua->get( $url );
        print "got $url: ", $res->title, "\n";
    };
}
$_->join for @coros;

__END__

[実行結果]
load http://d.hatena.ne.jp/hiratara/
load http://www.google.co.jp/
load http://www.yahoo.co.jp/
got http://www.google.co.jp/: Google
got http://www.yahoo.co.jp/: Yahoo! JAPAN
got http://d.hatena.ne.jp/hiratara/: a geek born in Tomakomai
</pre>

<p>全てのコンテンツの読み込みが同時にスタートし、並行して読み込みが行われていることがわかると思います。use Coro::LWPの部分をコメントにして動かした場合と結果を比較すると、より並行動作していることがはっきりするでしょう。</p>

<p>なお、非同期でHTTPアクセスを行うモジュールとしては、Coroの作者が作ったAnyEvent::HTTPというモジュールもあり、こちらのほうがよいとされています。ただし、Coro::LWPを使うと、LWPを使ったMechanizeやWeb::Scraperもそのまま動くという利点もありますので、ケースバイケースで選択するのがよいと思います。</p>

</div>
<div class="section">
<h3>実行の制御</h3>

<p>Coroのスレッドは、scheduleを呼ぶと眠り、readyで起こされると再び動き始めます。この働きをそのまま利用して実行の順番を調整することもできますが、これは大変です。例えば、以下のコードでは、他のスレッドに勝手にメインスレッドが起こされてしまっており、Doneの出力処理が実行されていません。</p>

<pre>
async {
	# The evil thread
	$Coro::main->ready;
};

my $done = $Coro::current;

async {
    print "Please wait.\n";
    cede;
    print "Done\n";
    $done->ready;
};

print "main thread\n";
schedule;
print "main thread, again.\n";

__END__
[実行結果]
main thread
Please wait.
main thread, again.
</pre>

<p>このような場合、Coroが用意しているロックの機構を利用し、実行の順序を明示的に指示する必要があります。例えば、Signalを使うと、この処理は以下のように書けます。</p>

<pre>
async {
	# The evil thread
	$Coro::main->ready;
};

my $done = Coro::Signal->new;

async {
    print "Please wait.\n";
    cede;
    print "Done\n";
    $done->send;
};

print "main thread\n";
$done->wait;
print "main thread, again.\n";

__END__
[実行結果]
main thread
Please wait.
Done
main thread, again.
</pre>

<p>waitメソッドは、sendが呼ばれるまでブロックします。そして、asyncブロックからsendを送ったタイミングで、メインスレッドのロックが解除されて再び動き出します。</p>


<p>また、カウンター付きのロックが必要な場合は、Semaphoreを使います。Signalのwaitの代わりに、downを使ってブロックさせることができます。downは文字通りカウンタの値を1減らすメソッドですが、カウンタが0以下の時はブロックして正の値になるのを待ちます。そして、ブロックしているSemaphoreを起こすにはupを呼びます。</p>


<p>以下の例では負(正確には0以下)の値のセマフォを作り、3つのプロセスが全て終了するのを待っています。</p>

<pre>
my $num = 3;
my $semaphore = Coro::Semaphore->new( 1 - $num );

for my $i ( 1 .. $num ) {
    async {
        Coro::Timer::sleep $i;
        print "After $i sec.\n";
        $semaphore->up;
    } ;
}

$semaphore->down;
print "Finished\n";
</pre>

<p>ここでAnyEventのcondvarに慣れている方であれば、beginとendのようなことをしたいと考えるかもしれませんが、downメソッドは0以下値の時はブロックするので、beginの代わりには使えません。この場合、負の値でもブロックしないadjustメソッドを使うことができます。</p>

<pre>
my $semaphore = Coro::Semaphore->new;

for my $i ( 1 .. 3 ) {
    $semaphore->adjust( -1 );
    async {
        Coro::Timer::sleep $i;
        print "After $i sec.\n";
        $semaphore->up;
    } ;
}

$semaphore->down;
print "Finished\n";
</pre>

<p>これとは逆に正の値のセマフォは、同時に走る処理の数を制御するのに便利です。以下の例では、2個しかないリソースを10個のスレッドが奪い合っていますが、セマフォによってリソースに同時に触れるスレッドを制限しています。</p>

<pre>
my $lock = Coro::Semaphore->new( 2 );
my @resources = ( 'A', 'B' );

for (1 .. 10) {
    async {
        $lock->down;
        my $resource = shift @resources or die "Depleted energy source.";

        print "Got $resource.\n";
        Coro::Timer::sleep 1;  # Using the resource

        print "Finished using $resource.\n";
        push @resources, $resource;
        $lock->up;
    };
}

schedule;
# Never end.
</pre>

<p>なお、この処理はguardメソッドを使って以下のように書くこともできます。</p>

<pre>
    async {
        my $guard = $lock->guard;
        my $resource = shift @resources or die "Depleted energy source.";

        print "Got $resource.\n";
        Coro::Timer::sleep 1;  # Using the resource

        print "Finished using $resource.\n";
        push @resources, $resource;
    };
</pre>

<p>この書き方をすると、セマフォのupのし忘れを防ぐことができます。ただしこの場合でも、upは確実に実行されてもリソースの解放処理が必ず走るわけではないので、Guardクラスを使って適切なガードを書く方が無難かもしれません。</p>
</div>
<div class="section">
<h3>スレッド間でのデータのやりとり</h3>

<p>スレッドが、処理した結果を返すにはterminateを使います。そして、その結果を受け取るにはjoinを使います。</p>

<pre>
my $coro = async {
	terminate "From the other thread";
};

print $coro->join, "\n";

__END__

[実行結果]
From the other thread
</pre>

<p>この例では明示的にterminateを呼んでいますが、asyncブロックは戻り値を渡してterminateを呼ぶように自動的にラップされるので、単にreturnで値を返してもjoinで値を受けることができます。</p>

<p>また、別のスレッドからcancelでスレッドをterminateさせることもできますが、この時に終了値を外のスレッドから渡すことが出来ます。</p>

<pre>
my $coro = async {
	print "Wait 10 sec.\n";
	Coro::Timer::sleep 10;
	terminate "From the other thread";
};

async {
	Coro::Timer::sleep 1;
	$coro->cancel( "Terminated" );
};

print $coro->join, "\n";

__END__

[実行結果]
Wait 10 sec.
Terminated
</pre>

<p>ただし、terminateとjoinでは、1つのスレッドから複数回値を返すことはできません。特にスレッドプールを使う場合には、スレッドが終了しないのでjoinが使えません。そこで、スレッド間でもっと自由にデータをやりとりする道具として、Coro::Channelがあります。Coro::Channelを使うと、簡単にスレッド間でデータのやり取りをすることができます。</p>

<pre>
my $ch = Coro::Channel->new;

async {
	$ch->put($_) for qw/one two three DAAAAA!/;
	$ch->shutdown;
};

while( my $got = $ch->get ){
	print $got, "\n";
}

__END__

[実行結果]
one
two
three
DAAAAA!
</pre>

<p>Coro::Channelの動作を、ブロッキングキューと見なすこともできます。デフォルトでは、大きさに制限のないキューとして振る舞います。つまり、putはブロックせず、getはキューが空の時だけブロックします。また、コンストラクタに値を与えることで、大きさ制限のあるキューとして利用することもできます。</p>
</div>
<div class="section">
<h3>スレッドへの割り込み</h3>

<p>cancelで他のスレッドを終了させることができることを紹介しましたが、スレッドを終了せずに割り込みをかけることもできます。そのためには、throwを使います。</p>

<p>別のスレッドに対してthrowを呼ぶと、あたかもthrowを呼ばれたスレッドの中でdieが起こったように動作します。evalでブロックする処理を包んだ状態にしておけば、外からthrowで投げられた例外をキャッチすることができます。</p>

<pre>
use Try::Tiny;

my $done = Coro::Signal->new;

my $worker = async {
	# The worker
	try {
		while () {
			print "In the loop.\n";
			Coro::Timer::sleep 1;
		}
	}catch{
		if( /interrupted/ ){
			print "Interrupted by anyone.\n";
			$done->send;
		}else{
			die $_;
		}
	};
};

async {
	# An interrupter
	print "Wait 3 seconds.\n";
	Coro::Timer::sleep 3;
	print "Interrupt.\n";
	$worker->throw( 'interrupted' );
};

$done->wait;

__END__
[結果]
In the loop.
Wait 3 seconds.
In the loop.
In the loop.
Interrupt.
Interrupted by anyone.
</pre>

</div>
<div class="section">
<h3>その他の話題</h3>

<p>このエントリでは、主にCoroの制御について説明しました。実際にCoroを使う場合は、主にIOの待ち時間を有効利用させることになります。Coroに対応したIOとしては、<a href="http://search.cpan.org/~mlehmann/Coro/Coro/Handle.pm">Coro::Handle</a>、<a href="http://search.cpan.org/~mlehmann/Coro/Coro/Socket.pm">Coro::Socket</a>、<a href="http://search.cpan.org/~mlehmann/Coro/Coro/AIO.pm">Coro::AIO</a>などがありますので、こちらを参照して下さい。</p>

<p>また、Coroは<a href="http://search.cpan.org/~mlehmann/AnyEvent/">AnyEvent</a>に対応したモジュールにおいて、コールバックが戻ってくるまでの待ち時間を有効利用するためにも使えます。CoroとAnyEventを組み合わせて使う方法については<a href="http://d.hatena.ne.jp/hiratara/20091219/1261178458">こちらのエントリ</a>や<a href="http://d.hatena.ne.jp/hiratara/20090930/1254319457">こちらのエントリ</a>も参照して下さい。</p>

<p>そして、たくさんのスレッドを扱う場合に有効な手段となるスレッドプールに関しては、<a href="http://d.hatena.ne.jp/hiratara/20091219/1261208413">こちらのエントリ</a>も参照して下さい。</p>
</div>
<div class="section">
<h3>まとめ</h3>

<p>Coroでスレッドを作り、並行動作させることができます。I/O待ちなどによってブロックが多く発生するプログラムでは、Coroによって動作速度を改善できるでしょう。</p>

<p>明日はあのAcme大全の著者、<a href="http://www.donzoko.net/">makamaka_at_donzoko</a>さんです。とても楽しみですね！</p>
</div>
<div class="section">
<h3>参考リンク</h3>
<ul>
<li><a href="http://d.hatena.ne.jp/starsky5/">Coro::Intro和訳</a></li>
</ul>
</div>
]]></description>
      <dc:creator>hiratara</dc:creator>
      <pubDate>Mon, 21 Dec 2009 00:00:00 GMT</pubDate>
      <category></category>
    </item>
    <item>
      <title>Acme::Oppaiで作る癒し系エイリアス</title>
      <link>http://perl-users.jp/articles/advent-calendar/2009/casual/20.html</link>
      <description><![CDATA[<div class="section">
<p>こんにちは！金曜日の天使だったacotieと申します。今の職業は猛獣使いをしている為、絶賛Perl勉強中です＞＜</p>
</div>
<div class="section">
<h3>はじめに</h3>

<p>まず、冒頭からアダルティな文字列が出てきます。苦手な人は戻って違うページを見て下さい。</p>

<p>世の中にはalias acotie="rm -rf ./*"などと設定されているすばらしい常識人もいらっしゃるようなので</p>

<p>見習って癒し系aliasを作ってみました。</p>

</div>
<div class="section">
<h3>インストール</h3>

<p>Acme::Oppaiモジュールのインストール</p>
<pre>
sudo cpan -i Acme::Oppai
</pre>

<p>.bashrcに追記</p>
<pre>
alias yappo="perl -MAcme::Oppai -e 'print Acme::Oppai->oppai('your')->oppai('soul')->oppai('message')->oppai;';"
</pre>

<pre>
$ source ~/.bashrc
$ yappo
</pre>
<pre>
　 _ 　∩
(　゜∀゜)彡　your


(　゜∀゜)彡　soul
　⊂彡
　 _ 　∩
(　゜∀゜)彡　message


(　゜∀゜)彡　おっぱい!
　⊂彡

</pre>



<p>余談ですが、Acme::Oppai-0.03よりnew()時にdefaultオプションが設定できるようになっていました。</p>

<h5> default => 'default'の場合</h5>
<pre>
perl -MAcme::Oppai -e 'print Acme::Oppai->new(default => 'default')->oppai';
</pre>
<pre>
　 _ 　∩
(　゜∀゜)彡　おっぱい!おっぱい!
　⊂彡


</pre>


<h5> default => 'up'の場合</h5>
<pre>
perl -MAcme::Oppai -e 'print Acme::Oppai->new(default => 'up')->oppai->oppai->oppai';
</pre>

<pre>
　 _ 　∩
(　゜∀゜)彡　おっぱい!

</pre>


<h5> default => 'down'の場合</h5>
<pre>
perl -MAcme::Oppai -e 'print Acme::Oppai->new(default => 'down')->oppai->oppai->oppai';
</pre>
<pre>

(　゜∀゜)彡　おっぱい!
　⊂彡
</pre>


<h5> 文字を入れることもできます！</h5>
<pre>
perl -MAcme::Oppai -e 'print Acme::Oppai->Oppai("Perl")->Oppai("Advent Calendar")->Oppai("2009!")';
</pre>
<pre>

　　　 _ 　∩
　　(　゜∀゜)彡　Perl
　　(　 　　|　
　 　|　　　|　
　 　し ⌒Ｊ
　　　 _ 　
　　(　゜∀゜)　　Advent Calendar
　　(　 ⊂彡
　 　|　　　|　
　 　し ⌒Ｊ
　　　 _ 　∩
　　(　゜∀゜)彡　2009!
　　(　 　　|　
　 　|　　　|　
　 　し ⌒Ｊ


</pre>

</div>
<div class="section">
<h3>まとめ</h3>

<p>Oppaiメソッド名の最初の文字を大文字にすると大きいAA、小文字だと小さいAAに変更することができます。</p>

<p>ストレスが溜まりやすい現代社会に、日常生活の癒しとしてAAを導入されてみてはいかがでしょうか。</p>


<p>明日は、Perl業界の最速レポーターなhirataraさんです！是非お楽しみに！</p>
</div>
]]></description>
      <dc:creator>acotie</dc:creator>
      <pubDate>Sun, 20 Dec 2009 06:00:23 GMT</pubDate>
      <category></category>
    </item>
    <item>
      <title>バカでもわかるPlack/PSGI</title>
      <link>http://perl-users.jp/articles/advent-calendar/2009/casual/19.html</link>
      <description><![CDATA[<div class="section">
<p>はじめまして。nobjasと申します。</p>
<p>今日はあまりにもネタがないために、</p>
<p>バカな僕がやっと最近使うことが出来たPSGIとPlack::Requestの使い方を書こうと思います。</p>
<p><br /></p>
<p>基本的な構造はmiyagawaさんのPlack Advent Calendar(<a href="http://advent.plackperl.org/">http://advent.plackperl.org/</a>)などで</p>
<p>紹介されているので、頑張って英語を読んでください（笑</p>
<p><br /></p>
<p>基本的にはPSGIはリクエストとレスポンスの形式の規約みたいなものです（と思っています）。</p>
<p>それを実装するのがPlackという訳ですね。</p>
<p><br /></p>
<p>そこで、まずは</p>
<p>Plackでリクエストを受け取ってレスポンスを返すCGIスクリプトを書いて見ましょう。</p>

<pre>
use Plack::Server::CGI;

my $app = sub {
    my $env = shift;
        return [
            200, 
            [ 'Content-Type' => 'text/plain' ],
            [ "Hello stranger from $env->{REMOTE_ADDR}!"],
        ];
};

Plack::Server::CGI->new->run( $app );
</pre>

<p>こんな風なファイルをhoge.cgiみたいにしてドキュメントルート以下に置けば、</p>
<p>Hello stranger from 192.168.1.1! みたいな表示がされます。</p>
<p>はい。簡単ですね。</p>
<p><br /></p>
<p>Plackでは、</p>
<p>リクエストはハッシュリファレンスで受け取り、</p>
<p>レスポンスは配列リファレンスで渡すとうまくごにょごにょして、</p>
<p>HTTPに変換してくれます。</p>
<p><br /></p>
<p>でもこれだけではなんだかたくさん書かないとダメですね。</p>
<p>リクエストもハッシュリファレンスのままだと何かと機能不足になる事があります。</p>
<p><br /></p>
<p>そこでリクエストをオブジェクトにしてレスポンスを作ってくれるモジュールがいます。</p>
</div>
<div class="section">
<h3> Plack::Request</h3>

<pre>
use Plack::Server::CGI;
use Plack::Request;

my $app = sub {
    my $env = shift;
    my $req = Plack::Request->new($env);
    my $res = $req->new_response(
        200,
        [ 'Content-Type' => 'text/html; charset=utf-8' ]
    ); # レスポンスオブジェクト作成
    $res->body("&lt;h1&gt;Hello, World&lt;/h1&gt;");
    return $res->finalize;
};

Plack::Server::CGI->new->run( $app );
</pre>

<p>注目すべきは、$res->body(...)ですね。</p>
<p>こうして、レスポンスオブジェクトを作成するようにすれば、</p>
<p>あとは皆様のご自由にWebApplicationを作れますね。</p>
<p><br /></p>
<p>この$appのところをMyApp->new()->psgi_handler()みたいに渡せば</p>
<p>あとはそのモジュールでPSGIのルールに沿ったロジックを作ればいいですね。</p>
<p><br /></p>
<p>これらのモジュールがあることで、</p>
<p>人それぞれのWeb Application Frameworkを作るのがとてもとても簡単になりました。</p>
<p><br /></p>
<p>今回はCGIで紹介しましたが、</p>
<p>このPlackを使って作成したモジュールはちゃんと作れば、</p>
<p>違うplatform(mod_perl, FCGI....etc)でそのまま動くようになります！</p>
<p><br /></p>
<p>それでは皆様素敵なPlackライフを！</p>
<p><br /></p>
<p>追伸: 最近BLOGを移行したので、宣伝させてくださいm(_ _)m</p>
<p>のぶじゃすのBLOG(<a href="http://blog.noble-jasper.com">http://blog.noble-jasper.com</a>)</p>
<p><br /></p>
<p>2009/12/21 追記:</p>
<p>Plack作者であるmiyagawa氏にはてぶでコメントをいただいた為、追記します。</p>
<blockquote>
<p>miyagawa  この例なら HTTP::Engine でよい <a href="http://twitter.com/miyagawa/status/6859126674">http://twitter.com/miyagawa/status/6859126674</a></p>
</blockquote>
<p>というコメントをいただき、恐る恐るリンクをクリックしてみると、</p>
<blockquote>
<p>Switching from $framework to Plack::Request makes NO sense. Stop publishing blog posts like that and confusing people "Plack is a framework"</p>
</blockquote>
<p>この例だけではセンスがないと言われてしまいました。</p>
<p>「Plackはフレームワークだ！」って書き方は止めましょうと。</p>
<p><br /></p>
<p>実を言うとHTTP::Engineはあまり詳しくないのですが、</p>
<p>Plack Advent Calendar を熟読し、Plackを再認識しまして。</p>
<p>追記をさせていただきます。</p>
<p><br /></p>
<p>miyagawa氏が</p>
<p><a href="http://advent.plackperl.org/2009/12/day-14-use-plackrequest.html">http://advent.plackperl.org/2009/12/day-14-use-plackrequest.html</a></p>
<p>ここで下記のように言っている通り、</p>
<blockquote>
<p>Directly using Plack::Request in the .psgi code is quite handy to quickly write and test your code but not really recommended for a large scale application. It's exactly like writing a 1000 lines of .cgi script where you could factor out the application code into a module (.pm files). The same thing applies to .psgi file: it's best to create an application class by using and possibly extending Plack::Request, and then have just a few lines of code in .psgi file with Plack::Builder to configure middleware components.</p>
</blockquote>
<p><br /></p>
<p><span style="color:red;font-weight:bold">大規模プロジェクトにおいて、</span></p>
<p><span style="color:red;font-weight:bold">Plack::Requestを使って.psgiファイル(実際に実行されるファイル)にコードを書いて、</span></p>
<p><span style="color:red;font-weight:bold">手軽にやるのは推奨されていないそうです。</span></p>
<p><br /></p>
<p><span style="color:red;font-weight:bold">アプリケーションレイヤーのコードを(.pmファイルなどのモジュール群に)Plack::Requestで記述し、</span></p>
<p><span style="color:red;font-weight:bold">.psgiファイルにはPlack::Builderを使って少ないコードでそれらを操作する事が良いそうです。</span></p>
<p>(日本語訳の解釈が間違っていましたらつっこみください。自信ないですw)</p>
<p><br /></p>
<p>せっかくのAdvent Calendarの記事だったのですが、作者から「あんまり良くなさそう」なコメントを頂いたので、とりあえず加筆しておきました。</p>
<p>今後Plackに関してはもっと自分でも勉強し、どこか(自分のBLOG等)にまとめて書きます。</p>
<p>というかmiyagawaさんの英文のPlack Advent Calendarを読むのがすごくためになると思います。</p>


</div>
]]></description>
      <pubDate>Sat, 19 Dec 2009 13:10:47 GMT</pubDate>
      <category></category>
    </item>
    <item>
      <title>Log::Dispatch::Screen::Color で色つきログでデバッグ！</title>
      <link>http://perl-users.jp/articles/advent-calendar/2009/casual/18.html</link>
      <description><![CDATA[<div class="section">
<p>
おはこんばんちは！ 絶賛無職中の vkgtaro です。おちこんだりもしたけれど私は元気です！<br />
今日はアプリケーションには欠かせないログに色をつけるよ！
</p>
</div>
<div class="section">
<h3> Log::Dispatch</h3>

<p><a href="http://search.cpan.org/dist/Log-Dispatch">Log::Dispatch</a> はログの出力先を標準エラーやファイルへの書き込み、メールで飛ばしたり、DBI で DB に突っ込んだり、と Log::Dispatch::* を指定して切り替えられる便利 logger です。</p>

<pre>
use Log::Dispatch;
use Log::Dispatch::File;

my $dispatcher = Log::Dispatch->new;
# ファイルへの出力
$dispatcher->add(
    Log::Dispatch::File->new(
        name      => 'file1',
        min_level => 'debug',
        filename  => 'logfile',
        mode      => 'append'
    )
);

$dispatcher->log( level => 'alert', message => 'Advent Calendar の締め切りが近い！ >_<');
# => logfile に Advent Calendar の締め切りが近い！ >_< と追記される
</pre>

<p>使いたい Log::Dispatch::* オブジェクトを add メソッドでどんどん追加できます。</p>

<pre>
use Log::Dispatch::Screen;

# Screen への出力も追加
$dispatcher->add(
    Log::Dispatch::Screen->new(
        name      => 'screen',
        min_level => 'debug',
        stderr    => 1
    )
);
$dispatcher->log( level => 'warning', message => 'ファイルと画面に出力されるよ');
# => 標準エラーに出力されつつファイルにも出力されます。
</pre>

<p>min_level はその Log::Dispatch::* オブジェクトが出力する最小のレベルです。max_level というオプションもあって、そちらは最大のレベルですね。</p>

<pre>
use Log::Dispatch;
use Log::Dispatch::Screen;

my $dispatcher = Log::Dispatch->new;

# min_level notice
$dispatcher->add(
    Log::Dispatch::Screen->new(
        name      => 'screen1',
        min_level => 'notice',
        stderr    => 1
    )
);

# max_level error
$dispatcher->add(
    Log::Dispatch::Screen->new(
        name      => 'screen2',
        min_level => 'debug',
        max_level => 'error',
        stderr    => 1
    )
);

$dispatcher->log( level => 'warning', message => 'notice ~ error なので2回表示される');
$dispatcher->log( level => 'debug', message => 'notice 以下なので1回だけ');
$dispatcher->log( level => 'emergency', message => 'error 以上なので1回だけ');
</pre>
</div>
<div class="section">
<h3> Log::Dispatch::Config</h3>

<p><a href="http://search.cpan.org/dist/Log-Dispatch-Config/">Log::Dispatch::Config</a> を使うと Log::Dispatch::* オブジェクトの追加とかを Config に書き出せておけます。</p>
<p>プログラムの方はこんな感じで書いておいて、</p>

<pre>
use Log::Dispatch::Config;

Log::Dispatch::Config->configure('log.conf');
my $dispatcher = Log::Dispatch::Config->instance;
$dispatcher->debug('デバッグログですよ');
</pre>

<p>指定した設定ファイルの方を以下の様に書くと</p>

<pre>
dispatchers = file screen

file.class = Log::Dispatch::File
file.min_level = debug
file.filename = logfile
file.mode = append
file.format = [%d] [%p] %m at %F line %L%n

screen.class = Log::Dispatch::Screen
screen.min_level = debug
screen.stderr = 1
screen.format = %m
</pre>

<p>
最初に示した例と同じようにファイルと標準エラーへの出力がされます。<br />
dispatchers には用意した設定で使わない設定を外すとその設定は使用されなくなります。便利ですね。
</p>

<p>Log::Dispatch::Config はいくつかの Configurator があるので XML や YAML 形式でも使えます。</p>
</div>
<div class="section">
<h3> Log::Dispatch::Screen::Color</h3>

<p>さて本題です！</p>

<p>色々書いてるうちに Log::Dispatch の話題がほとんどになってしまいましたが、<a href="http://search.cpan.org/dist/Log-Dispatch-Screen-Color/">Log::Dispatch::Screen::Color</a> で色をつけて終わりにしましょう。</p>

<p>せっかくなので <a href="http://search.cpan.org/dist/Log-Dispatch-Configurator-YAML/">Log::Dispatch::Configurator::YAML</a> を使って YAML で設定を示しましょう。</p>

<pre>
use Log::Dispatch::Config;
use Log::Dispatch::Configurator::YAML;

my $config = Log::Dispatch::Configurator::YAML->new('log.yaml');
Log::Dispatch::Config->configure($config);
my $log = Log::Dispatch::Config->instance;
</pre>

<p>設定はこんな感じ。</p>

<pre>
dispatchers:
  - color
color:
  class: Log::Dispatch::Screen::Color
  min_level: debug
  stderr: 1
  format: '[%d] [%p] %m at %F line %L%n'
  color:
    info:
      text: green
    warning:
      text: yellow
    error:
      text: red
    alert:
      text: red
      background: white
      bold: 1
</pre>

<p>そしてログを吐いてみます。</p>

<pre>
$log->info('info message is green!');
$log->warning('warning message is yellow!');
$log->error('error message is red!');
$log->alert('alert message is red on white!');
</pre>

<p>色ついた！</p>

<p><a href="http://vkgtaro.jp/img/jperl_advent_calendar_2009/log_color.png"><img src="http://vkgtaro.jp/img/jperl_advent_calendar_2009/log_color.png" alt="http://vkgtaro.jp/img/jperl_advent_calendar_2009/log_color.png" /></a></p>

<p>ログに色がつくと開発時とかわかりやすくて良いです。</p>

<p>ちなみに Log::Dispatch で色をつけるモジュールは拙作の <a href="http://search.cpan.org/dist/Log-Dispatch-Colorful/">Log::Dispatch::Colorful</a> なんてのもありますが、こっちは変数の dump もしたくて Log::Dispatch 自体にも手を加えてしまい、他の Log::Dispatch::* との共存がしづらくなります。</p>

<p>色をつけたいだけなら、Yappo さん作のこの <a href="http://search.cpan.org/dist/Log-Dispatch-Screen-Color/">Log::Dispatch::Screen::Color</a> をお薦めします。Windows 環境でも色が着くようです。</p>

<p>Catalyst でお手軽に色をつけたければ <a href="http://search.cpan.org/dist/Catalyst-Plugin-Log-Colorful">Catalyst::Plugin::Log::Colorful</a> なんてのもあります。</p>

<p>
<a href="http://search.cpan.org/~rra/ANSIColor-2.02/ANSIColor.pm">Term::ANSIColor</a> 使えばエスケープシーケンスを意識しなくても出力に色がつけられるので、他の Logger で色つけたいという方はモジュール作ってみてはいかがでしょうか！<br />
（Log::Dispatch::Screen::Color は Win32::Console::ANSI 使って windows 対策してますね）
</p>

<p><a href="http://vkgtaro.jp/img/jperl_advent_calendar_2009/nobjas_san.png"><img src="http://vkgtaro.jp/img/jperl_advent_calendar_2009/nobjas_san.png" alt="http://vkgtaro.jp/img/jperl_advent_calendar_2009/nobjas_san.png" /></a></p>

</div>
]]></description>
      <dc:creator>vkgtaro</dc:creator>
      <pubDate>Thu, 17 Dec 2009 13:10:47 GMT</pubDate>
      <category></category>
    </item>
    <item>
      <title>Proxy経由でLWP::UserAgentを使う</title>
      <link>http://perl-users.jp/articles/advent-calendar/2009/casual/17.html</link>
      <description><![CDATA[<div class="section">
<p>こんにちは！好きな寿司ネタは甘エビのkamipoです。</p>
<p>今日はProxy経由でLWP::UserAgentを使う方法を紹介したいと思います。</p>

<p>クローラやWeb APIなどを扱うモジュールの内部で必ずと言っていいほど使われているHTTPクライアントのLWP::UserAgentですが、世の中には色々な事情でHTTPリクエストするのにProxyを経由しなければいけない環境の人がいるんじゃないかと思います。</p>

<p>まず、LWPとCrypt::SSLeayの最新版をCPANからインストールしておきましょう。</p>

<pre>
% cpan LWP Crypt::SSLeay
</pre>

<p>LWP::UserAgentでProxyを指定するには以下のようにします。</p>

<pre>
#!/usr/bin/perl
use strict;
use warnings;
use LWP::UserAgent;

my $http_proxy = "http://forward_proxy:8080/";

my $ua = LWP::UserAgent->new;

# proxyメソッドを使う場合
$ua->proxy([qw(http https)], $http_proxy);

# 環境変数から読み込む場合
$ENV{HTTP_PROXY}  = $http_proxy;
$ENV{HTTPS_PROXY} = $http_proxy;

$ua->env_proxy;

my $res = $ua->get(shift);

print $res->dump;
</pre>

<p>一見するとこれでOKのように見えますが、この方法だとHTTPSのリクエストが失敗するようです。コマンドラインから以下のように実行してみましょう。</p>

<pre>
% perl proxy_sample1.pl http://http_host/
% perl proxy_sample1.pl https://https_host/
</pre>

<p>どうでしょう？HTTPSの場合だとステータスラインが</p>
<pre>
HTTP/1.0 501 Not Implemented
</pre>
<p>と返ってきたのではないでしょうか。</p>

<p>正解はCrypt::SSLeayのPODに書いてありました。</p>

<ul>
<li> <a href="http://search.cpan.org/dist/Crypt-SSLeay/SSLeay.pm#LWP::UserAgent_proxy_support">Crypt::SSLeay - search.cpan.org</a></li>
</ul>

<p>どうやらapacheのmod_proxy以外でのHTTPSリクエストのProxyは、LWP::UserAgent側でのハンドリングはせず、環境変数にセットしてCrypt::SSLeay側でProxyのハンドリングをしなければいけません。</p>

<p>つまり、HTTPもHTTPSも両方ちゃんと扱うには以下のようにする必要があります。</p>

<pre>
#!/usr/bin/perl
use strict;
use warnings;
use LWP::UserAgent;

# Crypt::SSLeayでは最後に"/"が付いてるとダメ
my $http_proxy = "http://forward_proxy:8080";

my $ua = LWP::UserAgent->new;

# proxyメソッドを使う(HTTPの場合)
$ua->proxy([qw(http)], $http_proxy);

# 環境変数から読み込む(HTTPSの場合)
$ENV{HTTPS_PROXY} = $http_proxy;

$ua->env_proxy;

my $res = $ua->get(shift);

print $res->dump;
</pre>

<p>もう一度コマンドラインから実行してみましょう。</p>

<pre>
% perl proxy_sample2.pl http://http_host/
% perl proxy_sample2.pl https://https_host/
</pre>

<p>今度はちゃんといけましたね！</p>

</div>
<div class="section">
<h3> なぜLWP::UserAgentではHTTPSをProxyできないのか</h3>

<p>なんとかProxyすることはできましたが、そもそも同じProxyを経由するのに同じ指定の仕方ができない理由は何か。LWPではだめなのか。</p>
<p>この挙動の原因はLWP::UserAgent::send_requestメソッドの以下のコードにありました。</p>

<pre>
sub send_request
{
    my($self, $request, $arg, $size) = @_;
    my($method, $url) = ($request->method, $request->uri);
    my $scheme = $url->scheme;

    local($SIG{__DIE__});  # protect against user defined die handlers

    $self->progress("begin", $request);

    my $response = $self->run_handlers("request_send", $request);

    unless ($response) {
        my $protocol;

        {
            # Honor object-specific restrictions by forcing protocol objects
            #  into class LWP::Protocol::nogo.
            my $x;
            if($x = $self->protocols_allowed) {
                if (grep lc($_) eq $scheme, @$x) {
                }
                else {
                    require LWP::Protocol::nogo;
                    $protocol = LWP::Protocol::nogo->new;
                }
            }
            elsif ($x = $self->protocols_forbidden) {
                if(grep lc($_) eq $scheme, @$x) {
                    require LWP::Protocol::nogo;
                    $protocol = LWP::Protocol::nogo->new;
                }
            }
            # else fall thru and create the protocol object normally
        }

        # Locate protocol to use
        my $proxy = $request->{proxy};
        if ($proxy) {
            $scheme = $proxy->scheme;
        }

        unless ($protocol) {
            $protocol = eval { LWP::Protocol::create($scheme, $self) };
            if ($@) {
                ... snip ...
</pre>

<ul>
<li> HTTPSリクエストでProxyなし
<ul>
<li> $protocolがLWP::Protocol::httpsのインスタンスになる</li>
</ul>
</li>
<li> HTTPSリクエストでProxyあり(Proxyの$schemeがHTTP)
<ul>
<li> $protocolがLWP::Protocol::httpのインスタンスになる</li>
</ul>
</li>
</ul>

<p>つまり、HTTPSリクエストでProxyありのときでも$protocolがLWP::Protocol::httpsのインスタンスになるようにすれば、HTTPリクエストもHTTPSリクエストも扱えそうですね！</p>

<p>そこで以下のコードを書いてみました。モジュール名はいい名前が思いつかなかったので適当です。</p>

<pre>
package LWP::UserAgent::ProxyConnect;

use strict;
use warnings;
our $VERSION = '0.01';

use LWP::UserAgent ();

{
    my $impclass = LWP::Protocol::implementor('http');

    my $orig = $impclass->can('request');

    my $proxy_method = sub {
        my ($self, $request, $proxy, $arg, $size, $timeout) = @_;

        # $request->url->schemeが'https'で$proxyがあるとき
        if ($request->url->scheme eq 'https' and $proxy) {
            # Crypt::SSLeayのために環境変数をセットして
            local $ENV{HTTPS_PROXY} = $proxy->host_port;

            no warnings 'uninitialized';
            my ($username, $password) = split /:/, $proxy->userinfo;
            local $ENV{HTTPS_PROXY_USERNAME} = $username;
            local $ENV{HTTPS_PROXY_PASSWORD} = $password;
            use warnings 'uninitialized';

            # $selfをLWP::Protocol::httpsのインスタンスにして
            bless $self, LWP::Protocol::implementor('https');

            # $proxyをなしにして元の処理に戻る
            $orig->($self, $request, undef, $arg, $size, $timeout);
        }
        else {
            goto $orig;
        }
    };

    no strict 'refs';
    no warnings 'redefine';
    *{"${impclass}::request"} = $proxy_method;
}

1;
</pre>

<p>LWP::UserAgentと同じように使えます。</p>

<pre>
#!/usr/bin/perl
use strict;
use warnings;
use LWP::UserAgent::ProxyConnect;

my $ua = LWP::UserAgent->new;

# 環境変数にセットしていればこれだけで両方ともOK
$ua->env_proxy;

my $res = $ua->get(shift);

print $res->dump;
</pre>

<p>これでリクエストがHTTPかHTTPSかを気にせずProxyを指定できるようになりました！やったね！</p>

<h4> 参考</h4>
<ul>
<li> <a href="http://d.hatena.ne.jp/ragtarou/20070302">Perlから、https(SSL)のコンテンツをProxy経由で取得する - ragutarouの日記</a></li>
<li> <a href="http://d.hatena.ne.jp/ikasam_a/20060413/1144910596">LWP::UserAgent::env_proxy - masakiのはてなダイアリー</a></li>
</ul>


<p>さてさて、JPerl Advent Calendar 2009もいよいよ後半に突入ですね。</p>
<p>明日はvkgtaroさんです！わくてか！</p>
</div>
]]></description>
      <dc:creator>kamipo</dc:creator>
      <pubDate>Wed, 16 Dec 2009 23:00:00 GMT</pubDate>
      <category></category>
    </item>
    <item>
      <title>Algorithm::SVMLight をインストールして使ってみよう</title>
      <link>http://perl-users.jp/articles/advent-calendar/2009/casual/16.html</link>
      <description><![CDATA[<div class="section">
<p>overlast（さとうとしのり）です。</p>

<p>僕は普段、自然言語処理技術を活用する仕事に従事しています。</p>

<p>Perl は「アイディアが浮かんでからコードを実行するまでの早さ」や「急で無茶な仕様変更への対応のしやすさ」などが好きで使っています。最初に Perl で実装して、後日速度が求められるようになったら、遅い部分だけ C / C++ で書き直すことが多いです。</p>

<p>Perl の CPAN モジュールの Author の方にはいつもお世話になっております。本当にいつもどうもありがとうございます。</p>

<p>さて今回は、教師あり学習を用いる識別手法の一つである Support Vector Machine（以下では SVM と略す） の実装の一つである SVMlight のための Perl モジュールの一つである「Algorithm::SVMLight」のインストール方法をご紹介します。</p>
</div>
<div class="section">
<h3> Support Vector Machine（SVM）はどんなことをしてくれるの？</h3>
<p>Support Vector Machine はパターン認識のための手法です。</p>

<p>SVM を分かりやすく説明するのは、思わず放棄したくなるほど困難なことなのですが、頑張ってみます。</p>

<p>たとえば、床にばらまかれた沢山のボールがあるとします。</p>
<p>ボールが落ちている位置に基づいて、すべてのボールを 2 つのバケツのどちらかに分けようと思います。</p>

<p>ボールの分け方には様々な方法があると思うのですが、</p>
<p>SVM による分け方は、ボール分けるときにロープを一直線に床に置いて、</p>
<p>ボールがロープより右にあるか左にあるかでバケツを分けるような分け方です。</p>

<p>大変にいい加減な図ですが、こんな図を思い浮かべてください。</p>

<pre>
       o
 o 　　
     o    o
--------------
  o      o
       o
            o
</pre>

<p>ロープの置き方は、なんでも良い、というわけではありません。</p>
<p>ボールを分けたときに、ロープの左右にあるボールとロープの距離の合計が最大となるようなロープの置き方をします。</p>

<p>ボールの位置が変わったときでも、このロープの置き方のルールを適用すれば、ボールは迷わずに 2 つのバケツに分けることができます。</p>

<p>ところで、もしもボールが明らかに 2 色にだけ別れているなら、以下のように分かれていても大丈夫な気分がしますね。</p>

<pre>
       o
 o 　　
     o    o
--------------
  x      x
       x
            x
</pre>

<p>では、ボールがこんな感じでバラまかれていたら、どこにロープを置くのでしょうか。</p>

<pre>
       x
 o 　　
     o    o

  x      x
       x
            o
</pre>

<p>なんというか、どうやってロープを置いても、まっすぐに置く限りは上手く2つのバケツに分けられなさそうですよね。</p>

<p>でも、もしも上の図が実は2次元の図ではなく3次元の図だったらどうでしょうか。</p>
<p>図を回転してあげたら、ロープをまっすぐ引いてボールを綺麗に分けられるような位置を見つけられるかもしれません。</p>

<p>SVM のすごいところは、これらのボールを何とか分けられるような空間にボールを写像して、なんとか線を引いてしまいます。</p>

<pre>
   x  |  
      |  o
      |   oo
      |
  xx  |   
   x  |  
      |   o
</pre>

<p>で、たとえば、こんな感じで線を引いてしまうのです。SVM にちょっと興味が出てきましたか？</p>

<p>ほんのりと SVM のことが分かってもらえれば、この説明は成功です。</p>

<p>SVM についてちゃんと知りたい方は、キチンと別の文献を読んで理解をし直してください。</p>
</div>
<div class="section">
<h3> 今回ご紹介するモジュール「Algorithm::SVMLight」</h3>
<p>今回、ご紹介する「Algorithm::SVMLight」は CPAN にある SVM 向けの Perl モジュールのうち、一番ちゃんと動きそうだから選びました。</p>
<p>でも、多少試行錯誤しないとインストールできなかったのでネタとして丁度良かったです。</p>
<p>インストールできなくて諦めてしまう人も多いかと思いますので、この記事を読んでガンバってみてください。</p>
</div>
<div class="section">
<h3> 「Algorithm::SVMLight」を使うと何が嬉しいのか</h3>
<p>SVMlightをPerlから扱えると何が嬉しいのかというと、インスタンスの読み込み、学習の実行、モデルの書き出し・読み込み、分類結果の取得などの動作を、Perl で書いたアプリケーションの任意の位置で実行できる点にあるのかな、と思います。</p>

<p>分類対象のデータを素性エンコーディングして、即、SVMlight で分類しようと思うようなときには、SVMlight が Perl から扱えると嬉しいです。分類結果を出力したあと、改めて素性エンコードする前のデータに結果に適用しようとすると、面倒くさいことが多いです。</p>

<p>Algorithm::SVMLight の作者である Ken Williams は、このモジュールにファイルからの分類対象データの読み込み処理を書いていません。「分類対象のデータに関しては Perl で扱え！」ということですかね。。。</p>

<p>ちなみに、学習データを SVM の学習用の素性にエンコードする処理に関しては SVMlight とは無関係に書けます。</p>
<p>でも、このエンコーディング処理は複雑になりがちなので、もろもろ柔軟な Perl はかなり重宝します。</p>
</div>
<div class="section">
<h3> SVM light と、Algorithm::SVMLight のインストール</h3>
<p>SVMlightの最新のソースコードは以下のURLからダウンロードできます。</p>

<ul>
<li> <a href="http://svmlight.joachims.org/">http://svmlight.joachims.org/</a></li>
</ul>

<p>今回、利用したソースコードは以下から取得しました。</p>

<ul>
<li> <a href="http://download.joachims.org/svm_light/current/svm_light.tar.gz">http://download.joachims.org/svm_light/current/svm_light.tar.gz</a></li>
</ul>

<p>その後は、以下のようにしてインストールしました。適時 sudo してください。</p>

<pre>
% wget http://search.cpan.org/CPAN/authors/id/K/KW/KWILLIAMS/Algorithm-SVMLight-0.09.tar.gz
% tar xfvz Algorithm-SVMLight-0.09.tar.gz
% mkdir ./svm_light
% cd ./svm_light
% wget http://download.joachims.org/svm_light/current/svm_light.tar.gz
% tar xfvz svm_light.tar.gz
% patch -p1 < ../Algorithm-SVMLight-0.09/SVMLight.patch
% make all
% mkdir /usr/local/bin/svm_light/
% cp ./svm_learn /usr/local/bin/svm_light/
% cp ./svm_classify /usr/local/bin/svm_light/
% mkdir /usr/local/include/svm_light/
% cp ./svm_learn.h /usr/local/include/svm_light/
% cp ./svm_common.h /usr/local/include/svm_light/
% cp ./libsvmlight.a /usr/local/lib
% cp ./libsvmlight.so /usr/local/lib
% ldconfig
% cd ../Algorithm-SVMLight-0.09/
</pre>

<p>バイナリファイルの名前を変えてコピーしているのは、変更前のファイル名が TinySVM と同じだったからです。</p>

<p>でも、このままだと Algorithm::SVMLight のコンパイル中に、SVMlight のヘッダファイルが見つからなくてエラーが出てしまいました。</p>
<p>仕方がないので、エディタで Algorithm-SVMLight-0.09/lib/Algorithm/SVMLight.c の 30・31 行目を編集し</p>

<pre>
#include "svm_common.h"
#include "svm_learn.h"
</pre>

<p>に、ヘッダの絶対パスを追記して、</p>

<pre>
#include "/usr/local/include/svm_light/svm_common.h"
#include "/usr/local/include/svm_light/svm_learn.h"
</pre>

<p>にしました。</p>

<p>あとは、以下を実行するだけでした。</p>

<pre>
% perl Makefile.PL
% perl Build
% perl Build test 
% perl Build install
</pre>

<p>これで SVMlight のインストールが終わり、Perl スクリプトからは Algorithm::SVMLight が使えます。</p>
</div>
<div class="section">
<h3> SVMlight の素性エンコード</h3>
<p>一番面倒なのが、データを素性形式にエンコード部分です。</p>

<p>素性の文字列表現と番号を対応づけるコードは、一回書くと使い回しが効いて楽です。</p>

<p>例えば以下のように実行できるエンコーダーを書いてしまって、</p>

<pre>
% perl feature_encoder.pl "入力の学習データファイルのパス" "出力の素性エンコード済みデータファイルのパス"
</pre>

<p>その後で、素性の作り方を工夫してみるのはどうでしょうか。</p>

<h4> feature_encoder.plの例</h4>
<pre>
#!/usr/bin/perl

use strict;
use warnings;
use utf8;

use Encode;

use TokyoCabinet;
use MeCab;

# MeCabオブジェクト
my @mecab_opt = ();
my $mecab = new MeCab::Tagger(join " ", @mecab_opt);

my $inputdata = $ARGV[0];
my $outputdata = $ARGV[1];
my ($in, $out);

# TokyoCabinetの初期化
my $tchdb_file_path  = $FindBin::Bin."/../feature_num.tch";
my $hdb  =  TokyoCabinet::HDB->new();
$hdb->tune(2000000);
$hdb->open($tchdb_file_path, $hdb->OWRITER | $hdb->OCREAT | $hdb->OREADER);

# 素性番号カウンタ
my $gloval_counter = 1;
# 素性番号カウンタの値をHDBから取り出すためのキー
my $gkey = "GLOBALCOUNTER";

# 素性番号カウンタの値を取得
my $tmp_gloval_counter = $hdb->get($gkey);
if (defined $tmp_gloval_counter) {
    $gloval_counter = $tmp_gloval_counter;
}
else {
    # 取得できなかったら初期値「1」を登録
    $hdb->put($gkey, 1);
    $gloval_counter = 1;
}

open ($in, "< $inputdata");
open ($out, ">> $outputdata");

# 素性の書き出し
while(my $line = <$in>){
    chomp $line;
    next unless ($line);
    # MeCabの結果を取得する
    my @mecab_arr = @{get_mecab_result_arr($line)};
    next unless (@mecab_arr);
    my $count = 0;
    
    # ラベル
    my $label = 0;

    # 出力用に素性番号を突っ込む配列
    my @feature_arr  =  ();
    
    # 素性の材料を得る
    my $entry = $mecab_arr[$i];
    my $key = $entry->[0];
    my $pos = $entry->[1];
    my $keypos = "$key:-:$pos";

    # 素性番号の取得と登録
    my @keyarr = ($key, $pos, $keypos);
    foreach my $k (@keyarr) {
         # 素性番号を取得してみる
         my $tmp_feature_num = $hdb->get($k);
         my $feature_num = 0;
         if (defined $tmp_feature_num) {
             # 取得できたら、そのまま出力用の配列に突っ込む
             push @feature_arr, "$tmp_feature_num";
	 }
	 else {
             # 取得できなかったら、素性番号カウンタの値を取得
	     $feature_num = $gloval_counter;
             # カウンタの値を、キーに対する素性番号にして登録
             $hdb->put($k, $feature_num);
             # 素性番号カウンタ++
             $gloval_counter++;
             # 素性番号カウンタのバックアップ
             $hdb->put($gkey, $gloval_counter);
             push @feature_arr, "$feature_num";
	 }
    }

    # ソート、ユニークする。
    @feature_arr  =  sort {$a < = > $b} @feature_arr;
    my $x   =   '-';
    my @uniq_arr  =  grep( $_ ne $x && ($x  =  $_), @feature_arr);
    # この例では、最後に全ての素性に一様な重みをつけている
    my $features  =  join ":0.1 ", @uniq_arr;
    my $entry  =  "$label $features:0.1\n";
    print $out $entry;

}
close ($out);
close ($in);
$hdb->close();

# 1行のテキストを受け取り、MeCabでparseしたあと、結果を配列に入れて返す。
sub get_mecab_result_arr {
    my ($line)  =  @_;
    my $parsed  =  $mecab->parse($line);
    $parsed  =  decode_utf8($parsed) unless utf8::is_utf8($parsed);
    my @pos_arr  =  split('\n', $parsed);
    my @result  =  ();
    if(@pos_arr){
        my $i  =  0;
        foreach my $pos (@pos_arr){
            my @info_arr  =  split(/\t/, $pos);
            my @mecab_arr  =  split(/\,/, $info_arr[1]);
            my @mec  =  ($info_arr[0], @mecab_arr);
            $result[$i]  =  \@mec;
            $i++;
        }
    }
    return \@result;
}
</pre>

<p>このファイルの中には TokyoCabinetを使った素性番号管理と、MeCab を使った形態素解析の処理が含まれています。</p>
<p>TokyoCabinetのHDBに、現在の素性番号の最大値を格納してあるので、追加も楽にできます。</p>
</div>
<div class="section">
<h3> SVMlight の素性エンコード時の注意点</h3>
<p>SVMlight に素性エンコードしたインスタンスを読み込ませるには、以下のような注意が必要です。</p>

<ul>
<li> インスタンス中の素性番号は昇順に並べること
<ul>
<li> 良い例：-1 10:0.1 20:0.2 30:0.3</li>
<li> 悪い例：-1 10:0.1 40:0.4 30:0.3</li>
</ul>
</li>
<li> インスタンス中の素性番号はユニークにすること
<ul>
<li> 良い例：-1 10:0.1 20:0.2 30:0.3</li>
<li> 悪い例：-1 10:0.1 20:0.2 20:0.3</li>
</ul>
</li>
<li> 学習データ以外の、分類対象のデータをエンコードする場合にもラベルを付与する</li>
</ul>
</div>
<div class="section">
<h3> Algorithm::SVMLight を使ったモデル構築</h3>

<p>Algorithm::SVMLight を使うと、モデルの構築は例えば以下のように書けます。</p>

<pre>
% perl ./make_model.pl "入力のインスタンスファイルのパス" "出力のモデルファイルのパス"
</pre>

<p>素性にエンコード済みなインスタンスファイルを用意できれば、上記を実行してあげるとモデルが得られます。</p>

<h4> make_model.pl の例</h4>
<pre>
#!/usr/bin/perl

use strict;
use warnings;
use utf8;

# オブジェクト作成
use Algorithm::SVMLight;
my $svm = new Algorithm::SVMLight;

# 入出力ファイルのパス
my $inputdata = $ARGV[0];
my $outputdata = $ARGV[1];

# インスタンスの読み込み
$svm->read_instances($inputdata);
# 学習開始
$svm->train();
# モデルの書き出し
$svm->write_model($outputdata);
</pre>

<p>Algorithm::SVMLight があれば、モデル構築以外の処理も Perl で手軽に書けます。</p>
</div>
<div class="section">
<h3> まとめ</h3>
<p>今回は SVMLight の Perl モジュールである Algorithm::SVMLight をインストールしました。</p>

<p>SVM は使いどころを間違えなければ大変に便利です。SVM を扱った学術論文は多数あるので、そちらもご覧下さい。</p>

<p>さてさて、明日は pixiv のエンジニアである kamipo さんです。楽しみですね！</p>
</div>
]]></description>
      <dc:creator>overlast</dc:creator>
      <pubDate>Tue, 15 Dec 2009 23:00:00 GMT</pubDate>
      <category></category>
    </item>
    <item>
      <title>PerlでEmEditorマクロを書こう</title>
      <link>http://perl-users.jp/articles/advent-calendar/2009/casual/15.html</link>
      <description><![CDATA[<div class="section">
<p>Songmuと申します。皆様初めまして。好きな言語はPerlと中国語だと公言しています。ただ、よく間違えられますが私も両親も日本人です。</p>

<ul>
<li>ブログ書いてます(<a href="http://www.songmu.jp/riji/">http://www.songmu.jp/riji/</a>)。</li>
<li>Wiki開発やってます(<a href="http://www.kuaiwiki.com/">http://www.kuaiwiki.com/</a>)。</li>
</ul>

<p>よろしくお願いします。</p>

<p>さて、今年はやたらVimヴィム言われた年であったように感じます。また、Web開発者のMac移行がより進んだ年であったようにも思いますが、ここで空気を読まずEmEditorの話をします。</p>
</div>
<div class="section">
<h3> EmEditorとは?</h3>

<p>Windows専用のテキストエディタであり、性能的には秀丸に比肩する能力を備えています。ただ、コミュニティの差なのか、秀丸に比べるとイマイチマイナーです。秀丸がWindowsテキストエディタ界におけるPerlだとしたら、EmEditorはRubyのような存在といえるでしょう(?)</p>
</div>
<div class="section">
<h3> EmEditorの特長</h3>

<p>個人的に優れていると思う点をあげてみます。</p>

<ul>
<li> Perl互換の正規表現での検索(秀丸に存在しない\b等も使える)</li>
<li> 中国語もGrepで引っ掛けられる</li>
<li> CSV, TSV表示機能がある(Ver.9以降)</li>
<li> Perlでマクロが書ける</li>
</ul>

<p>今回は、Perlマクロに関して取り上げます。JScriptで書かれることが多いみたいなのですが、Perlで書けるという事はCPAN使い放題なので、複雑な事も簡単に実現可能なのです。</p>
</div>
<div class="section">
<h3> マクロで何が出来るのか？</h3>

<p>百聞は一見にしかずということでまずは以下をご覧下さい。</p>

<dl>
<dt>TwitterTLを表示する</dt>
<dd><a href="http://songmu.jp/riji/img/emtwit.jpg"><img src="http://songmu.jp/riji/img/emtwit.jpg" alt="http://songmu.jp/riji/img/emtwit.jpg" /></a></dd>
<dt>選択範囲内の文字列をPerlコードとして実行・出力する</dt>
<dd><a href="http://songmu.jp/riji/img/emcode.jpg"><img src="http://songmu.jp/riji/img/emcode.jpg" alt="http://songmu.jp/riji/img/emcode.jpg" /></a></dd>
</dl>

<p>こんな感じのことができます。上記のように、個人的には</p>

<ul>
<li> 選択範囲のテキストを加工したりどこかに送ったり</li>
<li> 何らかの出力をアウトプットバー(画面の下半分の箇所)に出す</li>
</ul>

<p>といったことにマクロを活用しています。</p>
</div>
<div class="section">
<h3> 作成方法</h3>

<p>とりあえず簡単に。</p>

<ul>
<li>メニューから[マクロ] -> [カスタマイズ] -> [マイマクロ]タブで[新規作成]を押してファイルを作成</li>
<li>ファイルの拡張子は.pleeにする</li>
</ul>
</div>
<div class="section">
<h3> 書き出し</h3>

<p>以下の通りです。</p>

<pre>
#language="PerlScript"
our $Window;
 
use strict;
use warnings;
use utf8;
</pre>

<p>普通のPerlスクリプトとはshebang行の書き方が異なります。$Windowオブジェクトは既にEmEditorマクロ内で定義されているオブジェクトですが、use strictで書く場合は、ourで宣言しておかないと怒られます。</p>

<p>この$Windowオブジェクトを操作することがEmEditorマクロの肝となります。</p>
</div>
<div class="section">
<h3> $Windowオブジェクトについて</h3>

<p>EmEditorを弄る上で必要な、多種多様なメソッド・プロパティがぶら下がっています。オブジェクトの仕様に関しては、EmEditorのヘルプに詳細に書かれているので、そちらを参照すると良いでしょう。</p>

<p>ちなみに、EmEditorマクロはもともとVBScriptやJScriptで書かれることを想定しているので、Perlでメソッドやプロパティアクセスをしようとすると多少戸惑う部分があります。</p>

<p>Perlマクロの場合、プロパティアクセスもメソッド呼び出しも、メソッド呼び出しとして記述することが出来ますが、プロパティに値をセットするときには、オブジェクトの実体であるハッシュリファレンスの中を覗かないといけません。</p>

<p>また、真理値をセットする場合には、真を1、偽を0としてセットします。</p>

<pre>
// JScriptの場合
// アウトプットバーの内容を消す
Window.OutputBar.Clear();
// アウトプットバー非表示の場合、表示する
if ( !Window.OutputBar.visible ){
    Window.OutputBar.visible = true;
}
// アウトプットバーに'hoge'と表示する
Window.OutputBar.writeln('hoge');
</pre>

<pre>
# Perlの場合
# アウトプットバーの表示を消す
$Window->OutputBar->Clear;
# アウトプットバー非表示の場合、表示する
$Window->OutputBar->{'visible'} = 1     # ハッシュの中を覗く
    unless $Window->OutputBar->visible; # getterとしては使用可能
# アウトプットバーに'hoge'と表示する
$Window->OutputBar->writeln('hoge');
</pre>

<p>多分AUTOLOADを使って、メソッドが存在しない場合は、ハッシュエントリーを見に行くようにしているのでしょう。getterとして使用可能なら、$Window->OutputBar->visible(1) とかして、setterとしても使用可能でも良さそうなもんですが、それは出来ないようです。</p>

<p>ちなみに、毎回$Window->...とか書くのがめんどくさかったりする場合は、オブジェクトにアクセスするメソッドはオブジェクト参照を返すので、以下のように書くことが出来ます。当たり前ですが。</p>

<pre>
my $out_bar = $Window->OutputBar; # $out_barにOutputBarオブジェクトが入る
$out_bar->Clear;
...
</pre>
</div>
<div class="section">
<h3> 選択文字列(selectionオブジェクト)について</h3>

<p>プロパティアクセスの説明とともにOutputBarオブジェクトの説明も済ませてしまったので、次はselectionオブジェクトの説明をします。</p>

<p>selectionオブジェクトには、編集中のテキスト内の選択文字列の情報が入ります。OutputBarがマクロにおける出力部分だとしたら、selectionは入力の部分を担います。</p>

<p>以下のようにして選択文字列を取得することが出来ます。</p>

<pre>
my $code = Encode::decode(
    'cp932',
    $Window->document->selection->Text
);
</pre>

<p>cp932でデコードしています。日本語Windowsを使っている場合、selection->Textには必ずcp932文字列が入ってしまいす。たとえ、UTF-8のファイルを編集中であっても、その選択文字列は自動的にcp932文字列に変換されてselection->Textに入ってしまうのです。同様に、OutputBarに出力するときもcp932にエンコードしてやらなくてはいけません。</p>

<p>ロケールの問題なのか理由は定かではありませんが、これは非常に困ります。中国語(cp932範囲外の文字)が使えません。</p>

<p>ちなみに、JScriptでマクロを記述する場合には、スクリプトをUTF-8で記述し、BOMをつける事によって、UTF-8をそのまま扱うことが出来ます。つまり、OutputBarに中国語表示が可能です。この点はJScriptの方が優れています。悔しいです。</p>

<pre>
// JScriptだとUTF-8(BOM付き)で保存すると中国語が表示できる!!!
Window.OutputBar.writeln('你好');
</pre>

<p>これに関して解決策をご存じの方は、y.songmu at gmail.comまでお知らせ下さい。非常に困っています。</p>
</div>
<div class="section">
<h3> マクロの実例(実践編)</h3>

<p>気を取り直して、冒頭でも実行例を表示した、選択文字列をPerlコードとして実行するマクロを記載します。</p>

<p>これは簡単な計算をさせたり、正規表現のチェックをしたりとかなり重宝しています。</p>

<p>至極単純な話で、選択範囲をevalすれば良いだけの話なんですが、print, say文での出力をアウトプットバーに出したいため、IO::Captureモジュールを使って、捕捉した標準(エラー)?出力をアウトプットバーに出力しています。</p>

<p>IO::Captureモジュールはprint文が書かれてもその内容をすぐに出力せず、バッファしておくことができる、非常に便利なモジュールです。(一応モジュールの紹介もしておかないと)</p>

<pre>
#language="PerlScript"
our $Window;
use strict;
use warnings;
use utf8;
use Encode;
 
use Win32; # ダイアログ表示の為に使用
use IO::Capture::Stdout;
use IO::Capture::Stderr;
 
# 選択範囲のテキストを取得する
my $code = Encode::decode(
    'cp932',
    $Window->document->selection->Text
);
# 中身が空だったり、キャンセルされたら実行しない
exit unless $code;
# 実際はダイアログ表示させて無いんだけど、
# Win32モジュールを使う事も多いので合わせて紹介
exit if Win32::MsgBox('run?', 1) != 1;
 
# 標準(エラー)?出力の捕捉を開始する
my $capture = IO::Capture::Stdout->new;
my $stderr = IO::Capture::Stderr->new;
$capture->start;
$stderr->start;
 
# eval実行する
eval $code;
 
# 捕捉を終了する
$capture->stop;
$stderr->stop;
 
# 結果を出力する前にアウトプットバーの中身をクリアした後、表示
$Window->OutputBar->Clear;
$Window->OutputBar->{'visible'} = 1;

# 標準エラー出力を表示する
# readメソッドは捕捉した順番に出力内容をリストで返してくる
# 表示の際にはcp932でエンコードする
$Window->OutputBar->writeln(
    join "", map { Encode::encode('cp932', $_) } $stderr->read
);
 
$Window->OutputBar->writeln('---');
 
# 標準出力を表示する
$Window->OutputBar->writeln(
    join "", map { Encode::encode('cp932', $_) } $capture->read
);
</pre>
</div>
<div class="section">
<h3> マクロの実行について</h3>

<p>マクロメニューやマクロツールバーからマウスクリックで実行することも出来ますが、よく使うマクロにはショートカットキーを割り当てておくと良いでしょう。私も先程のPerlコード実行マクロには Ctrl+P を割り当てています。</p>

<p>また、メニューを「メニューの変更」から拡張することができます。メニューには Alt+任意のキー でアクセス可能なので、そこからマクロを呼び出したり、階層構造で管理をしたりすることも可能です。Perlの話から逸れるのでここでは多くは書きません。</p>
</div>
<div class="section">
<h3> マクロの使い所</h3>

<p>さて、ここまで読んできた方でEmEditor使いの方はもう、マクロをバリバリ書けるようになっていることでしょう。今後どう言ったマクロを書けば良いか、参考までに私が実際に作ったマクロの例を挙げます。</p>

<ul>
<li> Twitterに投稿する(と同時にOutputzにも送信する)</li>
<li> 手元のメモをメールで携帯に送る</li>
<li> コード(SQL等)を整形する</li>
</ul>

<p>等々です。外部プログラムとの連携も出来るので、頑張ればiTunesからプレイリストを拾ってきてコンテキストメニューに表示して選択したりなんかもできるようになるみたいです。</p>

<p>皆様も是非、Perlマクロを作ってみて下さい。便利だったら公開してみて下さい。</p>
</div>
<div class="section">
<h3> まとめ</h3>

<p>EmEditorでのPerlマクロ開発について駆け足で説明しました。マクロだけじゃなく、正規表現での一括置換なんかも強力なので、WindowでPerlを書くならEmEditorを是非オススメします。</p>

<p>質問、感想、意見なんかは、y.songmu at gmail.com まで連絡くださると嬉しいです。TwitterID: songmu なのでそちら宛につぶやいてくださっても喜びます。</p>

<p>明日はoverlastさんです。お楽しみに！</p>
</div>
]]></description>
      <dc:creator>Songmu</dc:creator>
      <pubDate>Tue, 15 Dec 2009 00:00:00 GMT</pubDate>
      <category></category>
    </item>
    <item>
      <title>パスワード保存のお供に Crypt::SaltedHash</title>
      <link>http://perl-users.jp/articles/advent-calendar/2009/casual/14.html</link>
      <description><![CDATA[<div class="section">
<p>こんにちは。はてなでは id:sfujiwara、それ以外のところでは fujiwara です。</p>

<p>Webサービスなどでユーザーのパスワードを預かる場合、「一方向ハッシュ関数を通した値を保存せよ」というのはよく知られた話だと思いますが、単に MD5 や SHA1 の値を保存するだけでは安全性に問題があります。</p>

<p>例えば <a href="http://search.cpan.org/~blwood/Digest-MD5-Reverse-1.3/lib/Digest/MD5/Reverse.pm">Digest::MD5::Reverse</a> というモジュールを使うと、MD5 の値を逆算することができてしまいます。</p>
<pre>
use Digest::MD5::Reverse;
print reverse_md5("388c3c9c00e651cc163cbdd47f08c427"); # fujiwara
</pre>
<p>実際には計算で求めているわけではなく、<a href="http://md5.rednoize.com/">http://md5.rednoize.com/</a> のようなハッシュ値を収集しているサイトから結果を得ているので、任意の値について逆算できるわけではないのですが、このように比較的容易に逆算できてしまっては危険ですね。</p>
<p># 他にも <a href="http://www.google.co.jp/search?q=f83a0aa1f9ca0f7dd5994445ba7d9e80">Googleで検索するとか……</a></p>

<p>ということで、このような場合は salt というランダムな値と一緒にハッシュ関数を通すことで、容易に逆引き一覧を用意できないようにして対抗するのが定石です。それを簡単にやってくれるのが <a href="http://search.cpan.org/~esskar/Crypt-SaltedHash-0.05/lib/Crypt/SaltedHash.pm">Crypt::SaltedHash</a> です。</p>

<p>文字列をハッシュ化するには</p>
<pre>
use Crypt::SaltedHash;
my $csh = Crypt::SaltedHash->new(algorithm => 'SHA-1');
$csh->add('secret');
print $csh->generate; # {SSHA}aeABWjt7Wq/UkrqTtUh9PbyoAnNndtSn
</pre>
<p>これで OK です。algorithm は省略すると SHA-1 になりますが、他にも MD5, SHA-256, SHA-512 などが指定可能です。salt が効くので、同じ入力値でも実行するたびに違う結果が得られます。</p>

<p>ハッシュ化された値から元の値を検証するには</p>
<pre>
$valid = Crypt::SaltedHash->validate($salted, 'secret');
</pre>
<p>これで真偽値が返ります。簡単ですね!</p>

<p>このモジュールがやってることは要するに、「乱数で salt を用意してもとの値と結合してからハッシュ関数に通す」だけなので、それぐらいなら自分でコード書いてもいいじゃないかと思われる方もいるかも知れません。</p>
<p>が、Crypt::SaltedHash が生成する値は、LDAP のパスワードを扱う方法を定義した RFC-3112 に準拠した形式になるというメリットがあります (ただし SHA-1, MD5 を使用した場合のみ)。</p>

<p>ある日突然、ユーザアカウントの管理を LDAP に移行したい! ということになっても、パスワードカラムの値をそのまま使えるのです。素晴らしいですね。</p>
<p># え、そんなこと滅多にない?</p>

<p>明日は Songmu さんです。お楽しみに!</p>
</div>
]]></description>
      <dc:creator>fujiwara</dc:creator>
      <pubDate>Sun, 13 Dec 2009 15:00:00 GMT</pubDate>
      <category></category>
    </item>
    <item>
      <title>﻿Test::Moreでテスト事始め</title>
      <link>http://perl-users.jp/articles/advent-calendar/2009/casual/13.html</link>
      <description><![CDATA[<div class="section">
<p>はじめまして。</p>
<p>最近Perlを始めたmyfinderです。</p>

<p>ほかの方が書いたCPANモジュールを紹介したりそれらを使ったTipsを書くCasual Trackということで、今回はテストに関連するモジュールについて書きます。</p>

</div>
<div class="section">
<h3> プログラムの「テスト」</h3>

<blockquote>
<p>テストを書くというのはデンタルフロスを使うようなもので、誰もが良いことだといいつつ、実際には軽視されがちだ。</p>
</blockquote>

<p>なんて言われることもありますが、実際テストがないとプログラムの改修とか引き継ぎとかが非常に大変になりがちです。</p>
<p>また、CPANにアップされているモジュールの中には、モジュール本体よりもテストコードの量の方が多いものも多々あります。</p>

<p>なのでプログラムの質を保証したり、内容を的確に伝達するにはテストが欠かせないものであることは間違いないと思います。</p>

</div>
<div class="section">
<h3> Test::More</h3>

<p>Perlのプログラムをテストするための枠組みを提供するモジュールです。</p>
<p>多くのモジュールでこれが使われています。</p>

<p>Test::Moreは5.6.2からコアモジュールに入っているので、最近のPerl環境なら誰でもすぐにテストを始めることができます。</p>

</div>
<div class="section">
<h3> 早速使ってみる</h3>

<p>例えば消費税の計算をしてくれるConsumptionTax::JPというモジュールを仮定してみます。</p>
<p>このモジュールは、tax_includeという関数に価格を渡すと消費税を付加した価格を返してくれるだけの簡単なお仕事をするクラスです。</p>

<p>が、簡単なお仕事でも間違った値が返ってくると困ってしまいます。</p>

<p>例えば</p>

<ul>
<li> 消費税込みの価格は原則小数点以下切り捨てなので、この関数が小数点を含む値を返してしまうことがあってはいけません。</li>
<li> 小数点が含まれた値を渡した場合、消費税の計算ができませんので、今回は入力された値も小数点以下を切り捨てて扱うこととします。</li>
</ul>

<p>というようなことは仕様として明確にしておかなければならないでしょう。</p>

<p>今回はそういった「プログラムを書く前に決まる(っている)仕様」を押さえるテストを書いてみましょう。</p>

<pre>
use strict;
use warnings;

use Test::More;

plan (tests => 5);

# 正しくuseできるかどうか
use_ok("ConsumptionTax::JP");

my $consumption_jp = new ConsumptionTax::JP->new({
    consumption_tax_rate => 0.05,
});

# tax_includeという関数を実装しているか
can_ok($consumption_jp, 'tax_include');

# 小数点以下の出ない値
my $price = 100;

my $price_in_tax = $consumption_jp->tax_include($price);

is($price_in_tax, 105, '期待値と一致');

# 小数点以下が出る値
$price = 128;

$price_in_tax = $consumption_jp->tax_include($price);

is($price_in_tax, 134, '期待値と一致');

# 小数点が含まれる値
my $price_in_point = 100.50;

$price_in_tax = $consumption_jp->tax_include($price_in_point);

is($price_in_tax, 105, '期待値と一致');
</pre>

<p>テストが書けたら、まずテストを動かしてみましょう。</p>

<pre>
$ perl t/consumption_tax.t
1..5
not ok 1 - use ConsumptionTax::JP;
#   Failed test 'use ConsumptionTax::JP;'
#   at t/consumption_tax.t line 9.
#     Tried to use 'ConsumptionTax::JP'.
#     Error:  Can't locate ConsumptionTax/JP.pm in @INC (@INC contains: /Users/myfinder/local-lib/lib/perl5/darwin-2level /Users/myfinder/local-lib/lib/perl5 /Users/myfinder/local-lib/lib/perl5/darwin-2level /usr/local/lib/perl5/5.10.1/darwin-2level /usr/local/lib/perl5/5.10.1 /usr/local/lib/perl5/site_perl/5.10.1/darwin-2level /usr/local/lib/perl5/site_perl/5.10.1 .) at (eval 4) line 2.
# BEGIN failed--compilation aborted at (eval 4) line 2.
Can't locate object method "new" via package "ConsumptionTax::JP" (perhaps you forgot to load "ConsumptionTax::JP"?) at t/consumption_tax.t line 11.
# Looks like you planned 5 tests but ran 1.
# Looks like you failed 1 test of 1 run.
# Looks like your test exited with 255 just after 1.
</pre>

<p>当然のことながらテストに失敗します。</p>
<p>これから、このテストを満たすプログラムを実装していきます。</p>

<pre>
package ConsumptionTax::JP;

use strict;
use warnings;

use base qw/Class::Accessor::Fast/;

__PACKAGE__->mk_accessors(qw/ consumption_tax_rate /);

sub tax_include {
    my ($self, $price) = @_;
    return $price * (1 + $self->consumption_tax_rate);
}

1;
</pre>

<p>実装ができたら、早速テストを走らせます。</p>

<pre>
$ perl t/consumption_tax.t
1..5
ok 1 - use ConsumptionTax::JP;
ok 2 - ConsumptionTax::JP->can('tax_include')
ok 3 - 期待値と一致
not ok 4 - 期待値と一致
#   Failed test '期待値と一致'
#   at t/consumption_tax.t line 30.
#          got: '134.4'
#     expected: '134'
not ok 5 - 期待値と一致
#   Failed test '期待値と一致'
#   at t/consumption_tax.t line 37.
#          got: '105.525'
#     expected: '105'
# Looks like you failed 2 tests of 5.
</pre>

<p>おっと、どうやら実装したプログラムは「計算結果に小数点以下の数が出た場合」と「小数点以下が含まれた値が渡された場合」を考慮しない作りになっていたようです。</p>
<p>このように、期待値と一致しない場合には通知してくれます。</p>
<p>早速期待通り動作するように修正します。</p>

<pre>
return $price * (1 + $self->consumption_tax_rate);
</pre>

<p>となっているところを、下記のようにします。</p>

<pre>
return sprintf("%d", $price * (1 + $self->consumption_tax_rate));
</pre>

<p>修正したので、テストします。</p>

<pre>
$ perl t/consumption_tax.t
1..5
ok 1 - use ConsumptionTax::JP;
ok 2 - ConsumptionTax::JP->can('tax_include')
ok 3 - 期待値と一致
ok 4 - 期待値と一致
ok 5 - 期待値と一致
</pre>

<p>今度は期待通りの挙動をしています。</p>
<p>これで、仕様を満たすプログラムが実装できました。</p>

</div>
<div class="section">
<h3> その他のテスト用関数</h3>

<p>今回はほぼisしか使いませんでしたが、他にも下記のようなものがよく使われたりします。</p>

<table>
<tr>
<th>関数</th>
<th>何をチェックするか</th>
<th>使い方</th>
</tr>
<tr>
<th>ok</th>
<td>真偽値</td>
<td>ok($val, '$val is true');</td>
</tr>
<tr>
<th>isnt</th>
<td>文字列が等しいかどうか</td>
<td>is($string, 'string', '$string is not "string"');</td>
</tr>
<tr>
<th>is_deeply</th>
<td>arrayやhashの比較</td>
<td>is_deeply($val, { key => 'val'}, '$val is match');</td>
</tr>
<tr>
<th>like</th>
<td>正規表現と一致するかどうか</td>
<td>like($val, qr/正規表現/, '$val is match');</td>
</tr>
</table>

<p>他にもいろいろなテスト用関数が提供されています。</p>
<p>詳しく知りたい場合はperldocなどを確認するのがよいです。</p>

</div>
<div class="section">
<h3> テストが増えてきたら</h3>

<p>開発しているモジュールの数が増えると、つられてどんどんテストファイルが増えていったりします。</p>
<p>そんなとき個別に</p>

<pre>
$ perl t/test.t
</pre>

<p>とかコマンドを打ちまくるのは刺身タンポポの香りがしてきます。</p>
<p>そんなときはproveコマンドを使うのがよいです。</p>

<p>proveコマンドはTest::Harnessについてくるコマンドラインツールです。</p>
<p>Test::Harnessもコアモジュールなので、特にインストールなどは不要です。</p>

<p>使い方は簡単で、</p>

<pre>
$ prove t/*.t
</pre>

<p>という風にコマンドを打つと、tディレクトリ以下にあるテストプログラムをまとめて実行してくれます。</p>

</div>
<div class="section">
<h3> おわりに</h3>

<p>今回は新規にでっち上げたモジュールのテストを書きましたが、当然既存のモジュールに対するテストを記述することも可能です。</p>
<p>師走の大掃除の際にソースコードを整理することがあると思いますが、その際には是非テストコードを書いてあげてください。</p>

<p>明日はsfujiwaraさんです。楽しみにしています！</p>


</div>
<div class="section">
<h3> 追記(done_testingについて)</h3>

<p>xaicronさんに「done_testingに触れてほしかったなう」とご希望いただいたので追記します。</p>

<p>done_testingとはTest::Moreの0.87から追加された機能です。</p>
<p>通常テストを書く際には</p>

<pre>
plan (tests => 5);
</pre>

<p>という感じにテストの数を指定しなければなりません。</p>
<p>指定しない場合は「no_plan」と書くように言われているドキュメントもありますが、これだと本来通らないはずのテストが通ってしまったりして、テストの意味がなくなってしまいます。</p>

<p>とはいえ開発途上でテストの数がどんどん増えたり、あるいは減ったりすることはよくある話です。</p>

<p>そんなときにはno_planを指定せず、テストコードの最後に</p>

<pre>
done_testing;
</pre>

<p>と書いておきましょう。</p>
<p>そうしておくと、明示的にテスト数を指定しなくてもテストが実行でき、かつテストが失敗した場合はその旨表示してくれます。</p>

<h4> SEE ALSO</h4>

<p><a href="http://d.hatena.ne.jp/tokuhirom/20090706/1246861746">http://d.hatena.ne.jp/tokuhirom/20090706/1246861746</a></p>
</div>
]]></description>
      <dc:creator>myfinder</dc:creator>
      <pubDate>Sun, 13 Dec 2009 10:00:00 GMT</pubDate>
      <category></category>
    </item>
    <item>
      <title>Perldocの話</title>
      <link>http://perl-users.jp/articles/advent-calendar/2009/casual/12.html</link>
      <description><![CDATA[<div class="section">
<p>lestrratこと牧です。AnyEventの話を書こうと思ったけど、それは本を書くくらいの厚さになりそうなのでやめました。「リアルタイムWebのためのPerl」って本書きたいので、編集さん誰か連絡ください。</p>

<p>ああ、advent calendarでした。</p>

<p>カジュアルトラックなので、カジュアルに使うために有用なテクニックってなんだったのかと考えたのですが、やっぱりperldocじゃないかな、と。僕がperlを2000年頃に使い始めてまず感動したのはドキュメントを漁りにネットに繋げなくてもよいということでした（当時はJavaを大学で使っていたので、ものすごく頻繁にjava.sun.comのjavadocページを見ていた）。</p>

<p>コマンドラインで</p>

<pre>
% perldoc CGI
</pre>

<p>ってするだけでCGI.pmのドキュメントが読めるんですよ？感動じゃないですか。manはそのままコンソールで読めるのに、javadocはなんでそれができないのかいつも不思議でした。今はもうそういうツールがあるのかもしれませんが、もうJava書かないのでどうでもいいです。</p>

<p>で、この<em>perldoc モジュール名</em>と<em>perldoc -f 関数名</em>という使い方は有名ですが、例えば$]って何が格納されてるの？とかのPerl本体の説明については意外とみんなどこにドキュメントがあるのか知らないので、その辺りをちらちらと書きたいと思います。</p>

<p>まず真っ先に、もし「どんなperldocあったか忘れちゃったなぁ・・・」以下のようにしてください。<em>"For ease of access, the Perl manual has been split up into several sections（簡単にアクセスできるようにPerlマニュアルはいくつかのセクションに分けられています）"</em>という文言の後にずらずらとperldoc経由で読めるマニュアル一式がでてきます。</p>

<pre>
% perldoc perl
</pre>

<p>ちなみに僕が使っているperl 5.8.8では約190個のエントリがならんでいました。</p>

<p>このうち、自分が比較的頻繁に読むセクションを紹介してみます：</p>
</div>
<div class="section">
<h3> perlvar</h3>
<p>perlvarはいわゆる巷で言われる「Perlの訳の分からない変数」がリストされています。変数は「<b>var</b>iable」というのでperl<b>var</b>です。下唇を噛んで発音して覚えて下さいね</p>

<p>このマニュアルを使うときは前半の説明とかどうでもいいので、お使いのビューアーの検索機能で探したい変数の名前を一気に探すのが吉です。</p>

<p>あと、このマニュアルにはuse Englishというものと、use Englishが提供する特殊変数の代替版がリストされています（例：$/ → $INPUT_RECORD_SEPARATOR)が、これはさっくり無視しましょう。use Englishはメモリも食う割にはあんまりメリットがないです。経験者は語ります。</p>

<p>ともあれ、特殊変数なんて別に暗記する必要もないので忘れる度にこのマニュアルを見に行ってます。僕が一案よく使う特殊変数は $]と$/ですね。</p>
</div>
<div class="section">
<h3> perlre</h3>
<p>これはいわゆる正規表現のマニュアルです。これまた文法をよく忘れるのでよく使います。perlvarと同じくビューアーの検索を使うのが吉ですが、何せ記号だらけなのでvimなどの正規表現を理解する検索システムではエスケープしなくてはいけないので余計に検索しにくいです。</p>

<p>個人的には"Extended Patterns"の項を一番よく使ってます。特に忘れがちなのが"zero-width look-ahead"系と"zero-width look-behind"系です。</p>

<pre>
$string =~ /(foo(?=bar))/; # fooの後にbarが存在したら、"foo"をマッチ
$string =~ /(foo(?!bar))/; # fooの後にbarが存在しなかったら、"foo"をマッチ
$string =~ /((?<=bar)foo)/; # fooの前にbarが存在したら、"foo"をマッチ
$string =~ /((?&lt;!bar)foo)/; # fooの前にbarが存在しなかったら、"foo"をマッチ
</pre>

<pre>
(?!)
</pre>
<p>はよく使うので覚えているのですが、それ以外はどうしても覚えられない。ちなみにここで検索する場合は上記のように"look-ahead"とか、そういうキーワードをちょっと覚えていると検索しやすいです。</p>

<p>その他正規表現の仕組みついて色々説明してくれているので、Jeffrey Friedl氏の名著「詳説 正規表現」にお金を出したくない人は読んでおくといいかもしれません。</p>
</div>
<div class="section">
<h3> perlopentut</h3>
<p>Perlのopen()関数は色々な使い道があるので結構忘れがちです。perlopentut（これ以後もそうですが、チュートリアル→<b>tut</b>orial→tutと覚えてくださいね）ではこのopenの様々な使い方を教えてくれます。</p>

<p>この章は特に検索に使うというより、とにかくopen() の使い方を教えてくれるので、暇な時にでも熟読してみるといいんじゃないでしょうか。open() のリファレンスとしては perldoc -f openのほうがいいかもしれません。</p>
</div>
<div class="section">
<h3> perlpacktut</h3>
<p>こちらはPerlのpack() 関数を教えてくれるチュートリアルです。バイナリアンじゃない僕はここに書いてあることがぼんやりとしかわかってませんが、とりあえずこれを読みながらmemcachedのバイナリプロトコルを実装したりしてました。perldoc -f packも、packのテンプレート種別が一気に表示されるので便利です。</p>
</div>
<div class="section">
<h3> perlipc</h3>
<p>IPCとはInter-Process Communicationの事で、要はプロセス間通信です。僕はfork()を使ったコードをある一定の周期で書くことが多いのですが、そのたびに子プロセスの回収の仕方を忘れるので毎回ここで見て思い出します。どうしてもwaitpidとかが思い出せないのです。で、いつもこんなコードを書きます：</p>

<pre>
use strict;
use POSIX qw(WNOHANG);

my %children;
my $to_fork = 10;

local $SIG{CHLD} = sub {
    while ( (my $pid = waitpid(-1, WNOHANG()) > 0 ) ) {
        delete $children{$pid};
    }
};

for my $i (1..10) {
    my $pid = fork();
    if (! defined $pid) {
        die "Failed to fork";
    }

    if ($pid) { # parent
        $children{ $pid }++;
    } else {
        # child
        local %SIG;
        ....
        exit;
    }
}

# なにかしながら%childrenが空になるのを待つ
</pre>
</div>
<div class="section">
<h3> perlxs, perlapi, perlapio, perlguts, perlclib</h3>
<p>PerlのCバインディングであるXSを書くときはこの辺りは必須です。</p>

<p>perlxsはXSの基本、perlclibはCレイヤーでPerlが提供するユーティリティ関数（メモリ確保とか、文字列比較とか）のリスト、perlapiはPerlの関数・マクロ群、perlapioはI/O関連のAPI、perlgutsは内部構造の説明等が載ってます。</p>

<p>正直XSのイントロとしては無理があるので、拙著「モダンPerl入門」を推したいところですが、個人的にはこれらのマニュアルと、Tim Bunce氏のMemcached::libmemcachedのソースコードが大変ためになりました。</p>


<p>以上個人的によく使っているマニュアル群でした。これ以外にも結構たくさんありますので是非どうぞ。ちなみに有志で日本語翻訳を行ってくれているperldocjpプロジェクトがいままで訳してきたそれらのマニュアルはこちらから入手可能です：<a href="http://perldoc.jp/docs/perl/">http://perldoc.jp/docs/perl/</a>。 5.10.x系まで揃ってるので英語が難しいという方はこちらもあわせてどうぞ。</p>




</div>
]]></description>
      <dc:creator>lestrrat</dc:creator>
      <pubDate>Fri, 11 Dec 2009 23:00:00 GMT</pubDate>
      <category></category>
    </item>
    <item>
      <title>Chart::Gnuplotでグラフを生成してみよう</title>
      <link>http://perl-users.jp/articles/advent-calendar/2009/casual/11.html</link>
      <description><![CDATA[<div class="section">
<p>本カレンダーの一エントリを担当させていただくにあたり，あわててgitとnimの勉強を始めたばかりの赤フレームなメガネの女性に惹かれるかもしれないissmと申します．他のエントリの方々と比べるとgeek度は皆無だったりしますが，この11日，おつきあいいだたければ幸いです．</p>

</div>
<div class="section">
<h3> 目次</h3>

<ul>
<li> はじめに</li>
<li> Chart::Gnuplotの概要</li>
<li> 準備</li>
<li> 基本</li>
<li> 実践</li>
<li> おわりに</li>
</ul>


</div>
<div class="section">
<h3> はじめに</h3>

<p>Perlでグラフを生成するためのモジュールとしては，グラフィックライブラリGDを利用した<a href="http://search.cpan.org/~bwarfield/GDGraph/">GD::Graph</a>とか，GoogleChart APIを利用した<a href="http://search.cpan.org/~dmaki/Google-Chart/">Google::Chart</a>とかが挙げられますが，最近，ふとしたきっかけで，Chart::Gnuplotなるモジュールの存在を知り，実際に使ってみたところ，なかなかいい感じでした．</p>

<p>今回は，そのChart::Gnuplotについて簡単に紹介してみます．</p>



</div>
<div class="section">
<h3> Chart::Gnuplotの概要</h3>

<p>グラフ描画系のツールのひとつに<a href="http://www.gnuplot.info/">gnuplot</a>というものがあります．</p>

<ul>
<li> <a href="http://www.gnuplot.info/">http://www.gnuplot.info/</a></li>
</ul>

<p>スクリーンショットを２点．</p>

<ul>
<li> <a href="http://farm3.static.flickr.com/2663/4166426208_a8aa809708_o.png">http://farm3.static.flickr.com/2663/4166426208_a8aa809708_o.png</a></li>
<li> <a href="http://farm3.static.flickr.com/2646/4165669881_f18a216d77_o.png">http://farm3.static.flickr.com/2646/4165669881_f18a216d77_o.png</a></li>
</ul>

<p>私の場合，大学在学時のレポートとか卒業研究とかが触れるきっかけでした．TeXで扱うためにEPS形式で出力したものがIllustratorでイジれるとを知って，何やら遊んでいた記憶くらいかありませんが．．．そんなことはどうでもいいですね＞＜</p>

<p>さて，このgnuplot，数式による描画もデータファイル読み込みによる描画もできたり，ラベルとか目盛りとかをはじめ，グラフ描画に関する様々な設定を細かく行えたりと，便利で高機能です．</p>

<p>そんなgnuplotをPerlから操作するためのインタフェイスを提供してくれるのが，このChart::Gnuplotです．</p>

<ul>
<li> <a href="http://search.cpan.org/~kwmak/Chart-Gnuplot/">http://search.cpan.org/~kwmak/Chart-Gnuplot/</a></li>
</ul>


<h4> 出力フォーマット</h4>

<p>Chart::Gnuplotは，描画したグラフの出力フォーマットとして，次のものをサポートしています．（出力先の拡張子によって自動で切り替えてくれるみたいですね．）</p>

<blockquote>
<p>The supported image formats are:</p>
<pre>
    bmp  : Microsoft Windows bitmap
    epdf : Encapsulated Portable Document Format
    epi  : Encapsulated PostScript Interchange format
    eps  : Encapsulated PostScript
    gif  : Graphics Interchange Format
    jpg  : Joint Photographic Experts Group JFIF format
    pdf  : Portable Document Format
    png  : Portable Network Graphics
    ppm  : Portable Pixmap Format
    ps   : PostScript file
    psd  : Adobe Photoshop bitmap file
    xpm  : X Windows system pixmap
</pre>
<p>If the filename has no extension, postscipt will be used.</p>

<p>cite: <a href="http://search.cpan.org/~kwmak/Chart-Gnuplot/lib/Chart/Gnuplot.pm#output">http://search.cpan.org/~kwmak/Chart-Gnuplot/lib/Chart/Gnuplot.pm#output</a></p>
</blockquote>

<p>これだけサポートしてくれていれば，まず困らないのではないでしょうか．</p>


<h4> グラフ描画</h4>

<p>gnuplotでは，2次元だけでなく，3次元の描画も行えます．もちろん，Chart::Gnuplotからでも可能です．</p>

<p>しかし，ここでは簡単に2次元描画にしぼって行きたいと思います．（私が試したことがないので．）</p>




</div>
<div class="section">
<h3> 準備</h3>

<p>前置きが長くなりましたが，まずは準備から．</p>

<blockquote>
<p>In order to use this module, gnuplot need to be installed. If image format other than PS, PDF and EPS is required to generate, the convert program of ImageMagick is also needed.</p>

<p>cite: <a href="http://search.cpan.org/~kwmak/Chart-Gnuplot/lib/Chart/Gnuplot.pm#DESCRIPTION">http://search.cpan.org/~kwmak/Chart-Gnuplot/lib/Chart/Gnuplot.pm#DESCRIPTION</a></p>
</blockquote>

<p>ということなので，gnuplotとかImageMagickとかをインストールしておきます．（ImageMagickは，PostScript・PDF・EPS形式以外のときに必要になります．入れておいて損はないかと思います．）</p>

<pre>
% sudo port install gnuplot
% sudo port install ImageMagick +perl
% sudo cpan -i Chart::Gnuplot
</pre>

<p>※ プラットフォームによって適宜置き換えてください．</p>


</div>
<div class="section">
<h3> 基本</h3>

<p>基本的な使い方は，だいたい次のような流れになります．</p>

<ul>
<li> 描画用データの準備</li>
<li> gnuplotオブジェクトの生成・設定</li>
<li> データセットオブジェクトの生成・設定</li>
<li> 描画・出力</li>
</ul>

<p>コードにすると，こんな感じです．</p>

<pre>
use Chart::Gnuplot;

# データの準備
my $xdata = [...];
my $ydata = [...];

# gnuplotオブジェクトの生成・設定
my $chart = Chart::Gnuplot->new(
  output => $filename,
  %opts_chart,
);

# データセットオブジェクトの生成・設定
my $dataset = Chart::Gnuplot::DataSet->new(
  xdata => $xdata, # arrayref
  ydata => $ydata, # arrayref
  %opts_dataset,
);

# 描画・出力
$chart->plot2d($dataset);
</pre>

<p>ちなみに，複数のデータセットを一度に描画することもできます．</p>

<pre>
my $dataset2 = Chart::Gnuplot::DataSet->new(...);

$chart->plot2d($dataset, $dataset2);
</pre>



</div>
<div class="section">
<h3> 実践</h3>

<p>もうちょっと実践的にやってみましょう．</p>


<h4> データファイル</h4>

<p>次のデータは，とあるサーバの負荷平均（ロードアベレージ）を，1日間，約10秒間隔で記録したものの一部です．（uptimeコマンドの出力を利用しています．）</p>

<pre>
1259593206,0.27,0.18,0.26
1259593216,0.31,0.19,0.27
1259593226,0.26,0.18,0.26
1259593236,0.22,0.17,0.26
1259593246,0.18,0.17,0.26
1259593256,0.16,0.16,0.25
1259593266,0.21,0.17,0.26
1259593276,0.18,0.17,0.25
1259593286,0.15,0.16,0.25
1259593296,0.13,0.15,0.25
...
1259679501,0.69,0.85,0.95
1259679511,1.20,0.96,0.98
1259679521,1.16,0.96,0.98
1259679531,1.38,1.01,0.99
1259679541,1.24,0.99,0.99
1259679551,1.12,0.97,0.98
1259679561,0.95,0.94,0.97
1259679571,0.80,0.91,0.96
1259679581,1.14,0.98,0.98
1259679591,0.97,0.95,0.97
</pre>

<p>このファイル名を，uptime.datとでもしておきます．</p>


<h4> データの読み込み</h4>

<p>データファイルにおける，コンマで区切った1列目（時刻）の系列を横軸，2列目（1分間の負荷平均値）の系列を縦軸としたグラフを生成することを考えてみます．</p>

<p>ということで，必要な部分を読み込みます．</p>

<pre>
my $t = [];  # １列目のデータ系列が入る
my $y = [];  # ２列目のデータ系列が入る

open my $fh, '<', 'uptime.dat'  or  die $!;
while (my $row = <$fh>) {
  #chomp $row;
  my ($time, $load) = split /,/, $row;

  # 時刻データを，00:00:00からの秒数に置き換える
  my ($ss, $mm, $hh) = (localtime $time)[0..2];
  $time = ($hh*60*60 + $mm*60 + $ss);
  $time /= 60*60;  # 1時間を0〜1の範囲に圧縮する

  push @$t, $time;
  push @$y, $load;
}
close $fh;
</pre>


<h4> gnuplotオブジェクトの準備</h4>

<p>次にgnuplotオブジェクトを生成します．</p>

<pre>
＃use Chart::Gnuplot; しているものとします

my $chart = Chart::Gnuplot->new(
  output    => 'uptime.png',
  imagesize => '1.5, 1.0',
  title     => '2009-12-01',
  xrange    => [0, 24],
  yrange    => [0, 3],
  xlabel    => 'time',
  ylabel    => 'load',
  grid => {
    width => 2,
    color => '#666666',
  },
  xtics => {
    along    => 1,
  },
  ytics => {
    along    => .5,
    labelfmt => '%.1f',
  },
  orient => 'landscape',
);
</pre>

<p>ここでのオプションの概要は次のような感じです．</p>

<dl>
<dt>output    </dt>
<dd>出力先</dd>
<dt>imagesize </dt>
<dd>出力の相対的なサイズ</dd>
<dt>xrange    </dt>
<dd>横軸の値の範囲</dd>
<dt>yrange    </dt>
<dd>縦軸の値の範囲</dd>
<dt>xlabel    </dt>
<dd>横軸につけるラベル</dd>
<dt>ylabel    </dt>
<dd>縦軸につけるラベル</dd>
<dt>grid      </dt>
<dd>補助線の種類とか色とか</dd>
<dt>xtics     </dt>
<dd>横軸の刻み</dd>
<dt>ytics     </dt>
<dd>縦軸の刻み</dd>
<dt>orient    </dt>
<dd>用紙（？）の方向</dd>
</dl>

<p>gnuplotを使われたことのある方にとっては馴染みのある単語が並んでいますね．</p>

<p>詳細はCPANの同モジュールのページをご覧ください</p>

<ul>
<li> <a href="http://search.cpan.org/~kwmak/Chart-Gnuplot/lib/Chart/Gnuplot.pm#Chart_Options">http://search.cpan.org/~kwmak/Chart-Gnuplot/lib/Chart/Gnuplot.pm#Chart_Options</a></li>
</ul>


<h4> データセットオブジェクトの準備</h4>

<p>先に準備したデータを基に，データセットオブジェクトを生成します．</p>

<pre>
my $dataset = Chart::Gnuplot::DataSet->new(
  xdata => $t,
  ydata => $y,
  style => 'impulses',
  color => '#ff0000',
);
</pre>

<p>ここでのオプションの概要は次のような感じです．</p>

<dl>
<dt>xdata </dt>
<dd>横軸のデータ</dd>
<dt>ydata </dt>
<dd>縦軸のデータ</dd>
<dt>style </dt>
<dd>描画の種類</dd>
<dt>color </dt>
<dd>描画の色</dd>
</dl>

<p>描画の種類によって指定する項目が異なったりします．詳細は次をご覧ください．</p>

<ul>
<li> <a href="http://search.cpan.org/~kwmak/Chart-Gnuplot/lib/Chart/Gnuplot.pm#Dataset_Options">http://search.cpan.org/~kwmak/Chart-Gnuplot/lib/Chart/Gnuplot.pm#Dataset_Options</a></li>
</ul>


<h4> 描画・出力</h4>

<p>あとは，次の1行で出力するだけです．</p>

<pre>
$chart->plot2d($dataset);
</pre>


<h4> できあがり</h4>

<p>すると，次のようなPNG画像ができあがります．</p>

<ul>
<li> <a href="http://farm3.static.flickr.com/2667/4166298909_c206912f66_o.png">http://farm3.static.flickr.com/2667/4166298909_c206912f66_o.png</a></li>
</ul>


</div>
<div class="section">
<h3> おわりに</h3>

<p>以上，Chart::Gnuplotの概要と，同モジュールを使ってグラフを生成する過程をざっと紹介してみました．</p>

<p>それでは，楽しいグラフ描画ライフをおすごしください．</p>



</div>
<div class="section">
<h3> さーて，明日のカジュアルさんは？</h3>

<p>冒頭で少し言及したGoogle::Chartモジュールの作者でもあるlestrratさんです．お楽しみに！</p>
</div>
]]></description>
      <dc:creator>issm</dc:creator>
      <pubDate>Fri, 11 Dec 2009 01:44:23 GMT</pubDate>
      <category></category>
    </item>
  </channel>
</rss>
