Perlの最近のブログ記事

なんだか寝れずに朝3時に起きてしまったので、書いてみる。

Perl で L10N といえば、Locale::Maketext::Lexicon ですが、間違った *.po ファイルを Gettext で指定すると、これでもかってくらいに探しまくるんですよね。例えば、実際に使いたい strings.po は /doko/soko/strings.poなのに、間違って /soko/strings.poを指定したとします。こんな感じ

    package Hello::I18N::de;
    use base 'Hello::I18N';
    use Locale::Maketext::Lexicon (Gettext => '/soko/strings.po');
    1;

すると、Gettext が SCALAR なので、Locale::Maketext::Lexicon::lexicon_get_() が呼び出されるんですが、ここでのファイルが見つからなかったときの探し方が。。

    my @path = split( '::', $caller );
    push @path, $lang if length $lang;

    $src = (
        grep { -e } map {
            my @subpath = @path[ 0 .. $_ ];
            map { File::Spec->catfile( $_, @subpath, $src ) } @INC;
          } -1 .. $#path
      )[-1]
      unless -e $src;

@INC で map して grep して -e って。$caler は scalar caller で定義されて Locale::Maketext::Lexicon が入ってるんだけど、結局のところ、たとえば手元の環境だと

/usr/lib/perl5/5.8.8/i686-linux/Locale/soko/strings.po
/usr/lib/perl5/5.8.8/Locale/soko/strings.po
/usr/lib/perl5/site_perl/5.8.8/i686-linux/Locale/soko/strings.po
/usr/lib/perl5/site_perl/5.8.8/Locale/soko/strings.po
/usr/lib/perl5/site_perl/5.8.5/Locale/soko/strings.po
/usr/lib/perl5/site_perl/5.8.4/Locale/soko/strings.po
/usr/lib/perl5/site_perl/5.8.3/Locale/soko/strings.po
/usr/lib/perl5/site_perl/5.8.2/Locale/soko/strings.po
/usr/lib/perl5/site_perl/5.8.1/Locale/soko/strings.po
/usr/lib/perl5/site_perl/5.8.0/Locale/soko/strings.po
/usr/lib/perl5/site_perl/Locale/soko/strings.po
/usr/lib/perl5/5.8.8/i686-linux/Locale/Maketext/soko/strings.po
/usr/lib/perl5/5.8.8/Locale/Maketext/soko/strings.po
/usr/lib/perl5/site_perl/5.8.8/i686-linux/Locale/Maketext/soko/strings.po
/usr/lib/perl5/site_perl/5.8.8/Locale/Maketext/soko/strings.po
/usr/lib/perl5/site_perl/5.8.5/Locale/Maketext/soko/strings.po
/usr/lib/perl5/site_perl/5.8.4/Locale/Maketext/soko/strings.po
/usr/lib/perl5/site_perl/5.8.3/Locale/Maketext/soko/strings.po
/usr/lib/perl5/site_perl/5.8.2/Locale/Maketext/soko/strings.po
/usr/lib/perl5/site_perl/5.8.1/Locale/Maketext/soko/strings.po
/usr/lib/perl5/site_perl/5.8.0/Locale/Maketext/soko/strings.po
/usr/lib/perl5/site_perl/Locale/Maketext/soko/strings.po
/usr/lib/perl5/5.8.8/i686-linux/Locale/Maketext/Lexicon/soko/strings.po
/usr/lib/perl5/5.8.8/Locale/Maketext/Lexicon/soko/strings.po
/usr/lib/perl5/site_perl/5.8.8/i686-linux/Locale/Maketext/Lexicon/soko/strings.po
/usr/lib/perl5/site_perl/5.8.8/Locale/Maketext/Lexicon/soko/strings.po
/usr/lib/perl5/site_perl/5.8.5/Locale/Maketext/Lexicon/soko/strings.po
/usr/lib/perl5/site_perl/5.8.4/Locale/Maketext/Lexicon/soko/strings.po
/usr/lib/perl5/site_perl/5.8.3/Locale/Maketext/Lexicon/soko/strings.po
/usr/lib/perl5/site_perl/5.8.2/Locale/Maketext/Lexicon/soko/strings.po
/usr/lib/perl5/site_perl/5.8.1/Locale/Maketext/Lexicon/soko/strings.po
/usr/lib/perl5/site_perl/5.8.0/Locale/Maketext/Lexicon/soko/strings.po
/usr/lib/perl5/site_perl/Locale/Maketext/Lexicon/soko/strings.po

これ全部 stat(2) して、「ぜぇぜぇ、がむばって探したけど無かったよ。じゃ、死にます」みたいな。いやぁ、そこまでがんばらなくていんだけどなぁ。そもそも scalar caller で $caller 定義しているのは本当にやりたいことなんだろうかとか思ったら 「scalar caller(1) でしょ?」ってのが RT に2年前に登録されてるな。まぁ、先にファイルが存在するのをチェックしないお前が悪いってことか。

まとめ: Locale-Maketext-Lexicon で Gettext でファイルを指定するまえに -e なりでそのファイルの存在を確かめましょう。DProfもいいけど strace を使うことで簡単に見つかるパフォーマンス改善ポイントもありますよという話でした。

あるウェブサイトから rel="me" というリンクを抽出して ActionStreams plugin の Other Profile に追加するスクリプト作った。ちょっといじれば tako3.com や fooo.name の情報から追加するものも作れるかと思います。


#!/usr/bin/perl -w

use strict;

use lib 'lib', '../../lib';
use MT::Bootstrap;
use MT;
use Web::Scraper;
use URI;
use Getopt::Long;

my ($uri, $author_id);

GetOptions(
'--uri=s' => \$uri,
'--author-id=s' => \$author_id,
);

die unless ($uri and $author_id);

package MT;

my %param;
sub param {
my $app = shift;
my $p = shift;
@_ ? $param{$p} = shift : $param{$p};
}
sub validate_magic { 1 }
my $user;
sub user {
unless($user) {
$user = MT->model('author')->load($author_id);
}
return $user;
}
sub uri {}
sub redirect {}

package main;

my $app = MT->new() or die MT->errstr;
my $scr = scraper {
process 'a[rel=~"me"]',
'profiles[]' => scraper {
process 'a', url => '@href';
};
result 'profiles';
};
my $profiles = $scr->scrape(URI->new($uri));

my $reg = $app->registry('profile_services');

my %services = map { $reg->{$_}->{url} => $_ }
grep {! $reg->{$_}->{ident_exact}} keys %$reg;

foreach my $profile (@$profiles) {
my ($ident, $type) = find_ident($profile->{url});
if ($type) {
add_profile($ident, $type);
}
}

sub find_ident {
my ($url) = @_;
my $ident;
my $type;
foreach my $url_pattern (keys %services) {
$ident = _find_ident($url_pattern, $url);
last if $ident and $type = $services{$url_pattern};
}
return $ident, $type;
}

sub _find_ident {
my ($url_pattern, $url) = @_;
$url =~ s{ \A http:// }{}xms;
$url =~ s{ / \z }{}xms;
my ($pre_ident, $post_ident) = split /\%s/, $url_pattern;
$pre_ident =~ s{ \A http:// }{}xms;
$post_ident =~ s{ / \z }{}xms;
if ($url =~ m{ \A (?:http://)? \Q$pre_ident\E (.*?) \Q$post_ident\E /? \z }xms) {
return $1;
}
## Grr.
$url =~ s{ \A www. }{}xms;
if ($url =~ m{ \A (?:http://)? \Q$pre_ident\E (.*?) \Q$post_ident\E /? \z }xms) {
return $1;
}
return;
}

sub add_profile {
my ($ident, $type) = @_;
my $app = MT->instance;
$app->param('author_id', $author_id);
$app->param('profile_type', $type);
$app->param('profile_id', $ident);

my @streams = keys %{ $app->registry('action_streams', $type) || {} };
foreach my $stream (@streams) {
my $param = join q{_}, 'stream', $type, $stream;
$app->param($param, 1);
}
use lib 'plugins/ActionStreams/lib';
use ActionStreams::Plugin;
use ActionStreams::Init;
my $ret = ActionStreams::Plugin::add_other_profile($app);
}

perl の Error.pm ってまだメジャーじゃないのかな。 Perlにおけるtry catch

Perlにおいてエラーなんかをトラップするための方法として、evalがあります。

http://perldoc.perl.org/functions/eval.html

で、まず一つ目としてこのevalはあくまで「関数」であって、構文ではありません。具体的にいうならば、

a = 1 / 0;

というものに対して、try catchをするのであれば、Javaならばこうすればいいわけです。

try{
a = 1 / 0;
}catch(Exception e){

}

perl についてくるモジュール Error.pm を使うとこんな感じで書けます。最後に ; が必要なのは一緒で、忘れがちなのも一緒ですがw。

#!/usr/bin/perl

use strict;
use warnings;
use Error qw(:try);

my $division_by = shift || 0;
my $a;

try {
    $a = 1/ $division_by;
    return $a;
}
catch Error with {
    my $e = shift;
    warn "XXX: " . $e->text;
};

catch したときの $e は Error::Simple オブジェクトです。

perl6だとどうなんだろう? CATCH が try の中にあるとかいう話も聞いたことがあるけど。。

try {
    &do_something;
    CATCH {
        &error_handling;
    }
}

perl regex performance

| コメント(0)

来日してる US の TypePad エンジニア Garth と話をしているときにでてきた正規表現の話。

$char =~ m/\p{Han}|\p{Hiragana}|\p{Katakana}/; #NG
$char =~ m/[\p{Han}\p{Hiragana}\p{Katakana}]/; #OK

return if $char =~ m/abc|def|ghi/; #NG
return if ($char =~ m/abc/ or $char =~ m/def/ or $char =~ m/ghi/); #OK

"|"(パイプ)を使った正規表現はめちゃくちゃ遅いから使わないように、ということです。確かにベンチマークを取ると32倍速いです。

#!/usr/local/bin/perl
use strict;
use warnings;

use Benchmark;

my $text = ';lskjdf;klvckxv;zijxcv;oa;vlkaefiuqewizlkvnzlxkcnv'
             . '.z,xmc v/z.x,cmv.z,xnvlafda isjdnfl aksjdfauerfaie'
             . 'jnlfakjdsn;akj;v akjdfvoaijdhfvoiaheriufahpsdiufhaeuhr'
             . ' iuahriufhairuhfapsidfalksjfhaiuphrofiankfjas;dofha[s9'
             . 'hfskjdf;ase;f,sedhfaiuwhefs,dnvflk dfis fapoisf fqjr';

my $count = 500_000;

timethese($count, {
   '00_pipe' => sub { $text =~ m/abc|def|ghi/ },
   '01_nopipe' => sub { $text =~ m/abc/ or $text =~ m/def/ or $text =~ m/ghi/ },
});

__END__
$ perl regex.pl
Benchmark: timing 500000 iterations of 00_pipe, 01_nopipe...
   00_pipe: 33 wallclock secs (32.48 usr +  0.01 sys = 32.49 CPU) @ 15389.35/s (n=500000)
 01_nopipe:  1 wallclock secs ( 1.73 usr +  0.00 sys =  1.73 CPU) @ 289017.34/s (n=500000)

punctuation variables

| コメント(0)

ひょんなことから perldoc perlvar とか perldoc -m English をつらつらと眺めてみました。 punctuation variables は「定義済み変数」って訳されているようです。

$@
EVAL_ERROR
$|
OUTPUT_AUTOFLUSH
$/
INPUT_RECORD_SEPARATOR
$!
OS_ERROR
$$
PROCESS_ID
$_
ARG

このへんは良く使いますね。最近知って便利かなぁと思ったのは以下のようなもの。

$.
INPUT_LINE_NUMBER

perl -ne 'printf "%05d: %s", $., $_;' hoge.pl とかで cat -n の代わりとかできますね。

$,
OUTPUT_FIELD_SEPARATOR

なんか簡単な print debug したいときとか $, = "\n"; print @data; とかやると、@data の中身が改行で区切られて出力されます。ま join "\n", @data でいんだけどさ。

まとめ

perl のスクリプトを読んで見慣れない $" 等の定義済み変数に出会ったら perldoc perlvar で内容を確かめましょう。

    use Acme::Hoge;

    print "foo bar baz foobar\n";
    # hoge fuga piyo hogefuga

    print "sidebar\n";
    # sidebar
    # (not be rewritten)

http://search.cpan.org/~mahito/Acme-Hoge/ fuga や piyo より gaga を使うことが多いです。

Output::Rewrite の作者の人がデモ用に作成したようです。 ex の下においておけばいいのに Acme::* を他のモジュールのデモで使うと CPAN ウォッチャーの目に留まりますね。

IO::All of it to Graham and Damian!

version: 0.34
date:    Mon May  8 01:03:12 PDT 2006
changes:
- Remove dependency on Spiffy.pm
- Apply patches and fix bugs from rt
- rt tickets - 11552 12048 14184 12966 13879 17105 7448 11463 7410 7337 7527
  18465

IO::AllSpiffy に別れを告げたようです。 とはいえ XXX は必要です。

追記
XXX の依存性は実際には無かったみたい。 0.35 で修正されました。 diff

YAPC::Asia is over

| コメント(0)

YAPC::Asia 2006 Tokyo が無事終了しました。

「楽しいことに最適化」「駱駝は楽だ」とかそういったフレーズが頭から離れません。 Larry, Damian, Audery といった perl コミュニティのコアにいる人々は 本当にそれを楽しんでいました。 彼らは未来を感じさせてくれるし、現状の問題や亜流に関して寛容。

いつも Shibuya.pm とかで感じるのは 宮川さん が楽しんで何か面白いことやっているから 自然と人が集まるという世界の面白さ。 それが YAPC::Asia によって世界の Perl コミュニティ規模で共感できたのが 個人的に一番嬉しかった。一番興奮したことでした。

参加していた方々も同じように興奮し、満足していたという様子は 最後 Wrap Up 後の長い拍手、片付けシーンの迅速さにに表れたと思います。 誰にでも出来ることはあるし、何か貢献することでコミュニティに入っていくことができる。 みんな、家に帰って何か作ってみようとか思ったのではないでしょうか?

私自身、スタッフの一員としてネットワークと格闘しておりましたが、 小展示ホールのネットワークで不具合があった点をこの場でお詫びします。 民生品とわたしのような素人ではなかなかしっかりとしたものを作れませんでした。 次回はもう少しがんばります。では、また次回 YAPC::Asia 2007 で!

今回のSF出張の準備として電子辞書を買いましたが、 PCで作業中に英語で分からない単語があると アルクの英辞郎 に問い合わせることも多いです。

ふと、どんな単語を問い合わせているのかなぁと作ってみたのが以下のスクリプト

Firefox はプロフィールフォルダ以下にある history.dat というファイルにブラウザの表示履歴データ を保存しています。 保存しているデータは Mork とかいう変態フォーマット。しかし CPAN にはすでに File::Mork という モジュールが存在していて、そいつにデータ解析を任せることが出来ます。 後は取得した File::Mork::Entry を料理するだけです。

YAPC::Asia 2006 Tokyo (Japanese): スピーカーとスポンサーが決定!

YAPC::Asia 2006 Tokyo のスピーカー・スポンサーを発表されました。 豪華なスピーカーです。先走って興奮してます。

せきむらまさよし も Lightning Talk で話す予定。 Perl Debugger の簡単な紹介をしたいなぁと思っております。

Pro Perl Debugging

| コメント(0)

さて、SF出張も一週間が過ぎました。USのエンジニアと一緒に作業すると 勉強になることも多いです。 一番便利だなぁと思ったのが perl -d でデバッグしていること。 はい。ずっと 'use Data::Dumper; warn Dumper($hoge)' を書いてデバッグしてました。

TypePad チームが使っているツールはちょっと工夫してあって、デバッガでのコマンドヒストリを保存して あります。これは 一旦デバッガを終了して、再度 perl -d しても以前のヒストリーが使えたりして便利です。

とはいえ、 perl -d はほとんど経験がないので宮川さんにコンピュータ関連の技術書が多いと 教えてもらった本屋 STACEY'S まで 雨の中(土曜日だってのに朝から雨)歩いていって Pro Perl Debugging: From Professional To Expert (Pro: from Professional to Expert) を買ってきました。 読みながらちまちまと体に染み込ませようかと思っております。

Pro Perl Debugging: From Professional To Expert (Pro: from Professional to Expert)
Richard Foley Andy Lester
Apress (2005/07/25)
売り上げランキング: 276,298

Catalyst-5.57PARをサポート? (MLをチェックしたら5.57にはバグがあるらしい。trunkではバグ修正済みとのこと。)

5.57    2005-11-20 22:45:00
        - Updated uri_for to accept undef actions
        - Switched to Module::Install
        - Renamed tests for easier editing
        - Reformatted documentation
        - Renamed -nonew to -force
        - Added PAR support
        - Added keep-alive support and bug fixes to HTTP engine.
          (Sascha Kiefer)
        - Added daemonize option to FastCGI engine. (Sam Vilain)

Shibuya Perl Mongers : Shibuya Perl Mongers テクニカルトーク #6

Shibuya Perl Mongersテクニカルトーク#6 を2005年11月2日に開催します。

出席します。Catalyst 等、いまどきな情報が満載のようで楽しみです。

use utf8; とすればスクリプトの中でUTF8が使える、という話を The Perl Journalの Simon Cozen 氏の記事 Ten Things You (Probably) Didn't Know About Perlで見かけた。どれどれ、と 変数名と関数名にUTF8を使ってスクリプトを書いてみた。(「package My::ひと;」は使えませんね「package My::ひと;」を使うには それより前で「use utf8;」すると良いようです(Inaba Hirotoさん情報。ありがとうございます))

package My::Person;
use utf8;
sub 新 {
    my $抽象的な名前 = shift;
    my %おぷちょん = @_;
    my $化身 = bless { なまえ => $おぷちょん{なまえ},
                       うまれ => $おぷちょん{うまれ} }, $抽象的な名前;
    return $化身;
}
sub なまえ {
    my $化身 = shift;
    return $化身->{なまえ};
}

package main;
my $せっきー = My::Person->新(なまえ => "Masayoshi Sekimura",
                              うまれ => "Hokkaido");

print $せっきー->なまえ,"\n";

実行した。

$ perl -w -Mstrict use_utf8.pl
Masayoshi Sekimura

驚いた。さらに、Filter::Pyuuta を思い出してしまったので悪ノリしてみた。

package My::Person;
use utf8;
use Filter::Pyuuta;

sub 新 {
    ここだけの話 $抽象的な名前 = 引っこ抜く;
    ここだけの話 %おぷちょん = @_;
    ここだけの話 $化身 = お清めをする { なまえ => $おぷちょん{なまえ},
                                 うまれ => $おぷちょん{うまれ} }, $抽象的な名前;
    戻る $化身;
}
sub なまえ {
    my $化身 = shift;
    戻る $化身->{なまえ};
}

package main;
ここだけの話 $せっきー = My::Person->新(なまえ => "Masayoshi Sekimura",
                                        うまれ => "Hokkaido");

書く $せっきー->なまえ,"\n";

「ここだけの話」がブログ女王の接頭辞になりつつあるこのご時世、トラックバックがたくさんやってきそうなスクリプトになりました。(Filter::Pyuuta は EUC-JP から UTF-8 に変換する必要があります。あと shift と bless をmapに追加しないといけません)

yaml ファイルで書かれた設定ファイルとかの差分を調べるために diff を取ろうとすると 以下 diff -u file1.yaml file2.yaml のようにどのキーの値が違うのかがわかりにくい。

-- file1.yaml  2005-10-18 00:22:33.000000000 +0900
+++ file2.yaml  2005-10-18 00:22:53.000000000 +0900
@@ -1,9 +1,11 @@
-template:
-  path: /home/sekimura/templates
 database:
   host:     localhost
   port:     5432
-  passwd:   dbpasswd
   user:     dbuser
+  passwd:   dbpassword
 app:
   name: Sandbox
+template:
+  path: /home/sekimura/templates
+author:
+  name: Masayoshi Sekimura

そんなわけで簡単なYAMLをキー単位で差分を取る ydiff というツールを作ってみた。 ydiff file1.yaml file2.yaml を実行した結果が以下。

--- file1.yaml database
+++ file2.yaml database
@@ -1,5 +1,5 @@
 ---
 host: localhost
-passwd: dbpasswd
+passwd: dbpassword
 port: 5432
 user: dbuser
--- file1.yaml author
+++ file2.yaml author
@@ -1 +1,2 @@
---- ~
+---
+name: Masayoshi Sekimura

この diff でそのまま patch を当てるってことはできないけども、 databaseキー の passwd にスペルミスっぽいのがあるのと、 file1.yaml にauthorキーが無いのがわかる。十分便利。

ちなみにこんなスクリプトです。

#!/usr/bin/perl
use strict;
use warnings;

use YAML qw(LoadFile);
use Text::Diff;

my ($file1, $file2) = @ARGV;

my $yaml1 = LoadFile($file1, NULL);
my $yaml2 = LoadFile($file2, NULL);

my %all_keys = map { $_ => 1 } (keys(%$yaml1), keys(%$yaml2));
for my $key (keys %all_keys) {
    print diff(\YAML::Dump($yaml1->{$key}), \YAML::Dump($yaml2->{$key}),
                   {
                       FILENAME_A  => $file1." ".$key,
                       FILENAME_B  => $file2." ".$key,
                   });
}

YAMLがハッシュでないと動かないけど、たいていの設定ファイルはこんな感じなのでOKかと。

versions_perl.gif

Debian sarge の perl は 5.8.4 なんですが、 Class::DBI を make test すると t/16-reserved でFAILする。(DBD-SQLite は 1.08 を使用)

t/16-reserved.........ok 2/5Argument "Bad Taste" isn't numeric in 
subroutine entry at 
/usr/lib/perl5/site_perl/5.8.4/DBIx/ContextualFetch.pm line 51.
#     Failed test (t/16-reserved.t at line 27)
#          got: undef
#     expected: '10'
t/16-reserved.........ok 5/5# Looks like you failed 1 tests of 5.

調べてみると perl 5.8.4 以前で looks_like_number に undef を 放り込んだときに真を返してしまうバグらしい。 http://use.perl.org/comments.pl?sid=25179&cid=38508 そのバグが原因で DBD::SQLite の dbdimp.c の内部で使っている looks_like_number に反応して undef の value を double で bind するのが、Class::DBIのテストでエラーになる原因ってそんな状況。

cdbi-talk で Class::DBI 0.96 and perl 5.8.3 - bad combo? という話題がありましたが、多分原因は一緒。

解決方法としては、5.8.5以上(現在 Stable は5.8.6)をインストールするか、debian package に patch をあてて再インストールするかですね。

今回は Catalyst の Action の定義の仕方や処理の流れについて書いてみます。 Catalyst::Manual::Intro の Action にある説明を簡単にご紹介しますので、version 5 になってかっこよくなった action 定義の仕方を大雑把にでも理解できるかと思います。

Sledgeという オープンソースなWebアプリケーションフレームワークがあります。 けど、なかなか流儀を覚えるのが大変で、最初の一歩がとても遠く感じる人も 多いかと思います。 そこで、ここ最近の Rails な フレームワークにる helper スクリプトを Catalyst::Helper を参考にしつつSledge向けに作ってみました。

Sledge-Helper-0.04.tar.gz
MD5 (Sledge-Helper-0.04.tar.gz) = 76587f4f8c8746bf5cfdabcf971cc418

Helperスクリプトといっても、lib, template, htdocs 等を一気に作ってくれるsledge-helper.pl と、開発時の動作確認用につかう簡易httpサーバになる server.pl だけです。(キッパリ!) 使い方は sledge-users ML への投稿を参考にしてください。

で、肝心なものが無いわけです。 controller(SledgeでいうところのPages::Hoge.pm)を 追加するcreator や、データベースのテーブルを指定するだけで create, update, delete (CRUDと呼ばれますね) がWebIFで できるように自動的に作成してくれるもの、 テストスクリプトの自動作成はありません。(Catalystには最初からあります)

まぁ、少ないながらもHelperと呼ばれるものを作ってみてわかったことがあります。 今度、フレームワークを作るときはHelperも含めて設計したほうがいいよねってことですね。よりアジャイルで変更を恐れずバリバリのテスト駆動で開発する場合は必須な武器になるだろうということ。 そして、使うのもいいけど作るのも面白いよねということです。

2005年4月13日 追記
0.03 は $self->r->param('hoge') の扱いがまったく出来ていなかった(すみません。TT param 動いているのしか確認してなかったです)ので 0.04 を作成しました。

[Catalyst] Win32 Catalyst Demo

Installing Catalyst Hops SQLite Sample on a Clean Win2k Installation

Catalyst を Windows で動かす方法がMLにポストされました。 ActivePerl, SQLite, ppm, nmake, CPAN といったキーワードに明るくないと 苦労しそうですが、時間のある方は挑戦してみては?(つまり私は時間が無い。。)

3月26日のOSC2005に行ってきて、Ruby on Rails(以下 RoR) な話をチラリと聞いてきました。実際にその場でアプリケーションを作るというまな板プレゼンと「高橋メソッド」で RoR が生まれた背景や考え方を紹介という内容。とても面白かったです。

Perl の世界でも Maypole をベースにして開発され最近(多分RoRを意識して) 開発が進められている Catalyst という MVC フレームワークがあります。 helper スクリプト、開発用の小さなhttpd等 RoR そっくりです。

今回は Catalyst がどんなものかと、例の 「TinyURL を実装」という形で基本的な部分をご紹介します。 ちなみに、以下のコードは1時間では作成できず、YAPC::Taipei を眺めながら 3時間くらいかかってしまったです。。 でも、 Catalyst の使い方を覚えるのを含めての時間なので大目に見てくださいね。

追記 2005年4月6日
Bundle::Catalyst::Everything をしないと例にしているスクリプトは動作しないそうです。
(んと、また多分後で追記します。)

XML::Feed の使い方。

| コメント(0)

Ben Trott 氏作成の XML::Feed を使ってみました。 XML::Feed の特徴は RSS 0.91, RSS 1.0, RSS 2.0 そして Atom に対応していて、これらのデータに統一されたAPIを提供してくれます。

特に気持ちいいのが $feed->modified も $entry->modified も DateTime オブジェクトを返すので $feed->modified->ymd とすれば 2004-12-31 という文字列が 返ってくるところ。

自前で作っていた Blog crawler の処理は XML::RSS 任せだったので Atom に対応してませんでしたが、XML::Feed を使えば 簡単に対応できそうです。以下に簡単なスクリプトを。

YappoLogs: お気に入りのPerl Module管理サイト公開

CPANに登録されている気に入ったモジュールをコメントつきで簡単に管理できるサイトを作ってみました。

via antipop

お気に入りのCPANモジュールを登録し、JavaScriptでBlogに貼り付けられるサービス。ニッチなサービスですけど、アイディアと実装したという事実が素敵。 Perl Hacker がこぞって利用し始めるとおもしろいかも。みなさん登録!

いまどき的には、以下機能が追加されるともっと楽しめるかも。(半分冗談)

  • お気に入りの近隣検索して、Perlモジュール嗜好の近い人を表示(で、どうするって話はあるけど)
  • 友達登録機能。(そんなにたくさん友達いるだろうか。。)
  • Perlモジュールにタグをつけて管理(そもそも名前でディレクトリ構造表してますが)

use Perl | "Practical mod_perl" book goes opensource

Books stas writes : "The complete "Practical mod_perl" book is now available online under the terms of the CreativeCommons "Attribution Share-Alike License". Thanks to all who have purchased our book so far. You can still get the printed version from your favorite book store and it will certainly make a nice "light" XMas present (hint, hint :)."

Oreillyから出ている mod_perl 本が http://modperlbook.org/で 読めるようになってますね。
(via void GraphicWizardsLair( void ); //)

Autocomplete CPAN Search

| コメント(0)

teknikill.com - Autocomplete CPAN Search Site

As you type, this site will autocomplete based on all CPAN modules. Borrowed from Google Suggest
cpan suggest screenshot

続々々・「しーぱん」なのか「くぱん」なのかハッキリさせよう で、めでたく「しーぱん」になった search.cpan.org に Google Suggest のキーワード予測を組み込んだ 例を公開しているサイト。
(via Perl Monks : Google Suggest)

Google Suggest の仕組みは Slashdot とかで調べると手元のFireFoxの場合はフォームの文字列が変わるたびに HTTP GET で /cgi-bin/search にリクエストを送って、そのレスポンスとして返ってくる配列を定義する JavaScript のコードを使ってプルダウンメニューを表示させているようだ。 (詳しく知りたい人は ac.js Google suggest をGoogleで検索 してくださいませ。)

この Autocomplete CPAN Search では予測キーワードを取得する /cgi-bin/search の変わりにモジュール名を検索するスクリプトを用意して Google Suggest と同じような動きをさせていますね。

Shibuya Perl Mongers テクニカルトーク #5 行ってまいりました。 やっぱり面白いこのイベントに、 会場が近いというか、会場係というか、そんな形で関われたのは幸いです。 次回あたりでは是非ともなんかしゃべりたいなぁ。。 で、内容は非常にボリューム満点。 18:30 - 21:30くらいやってた?最近体力落ち気味のワシャちとお疲れ?

ま、perl で「固定長文字列を取り出すなら substr() が速い」 という、ごく自然な話です。。

search.cpan.org: Flickr::Upload - Upload images to flickr.com

Flickr::Upload - Upload images to flickr.com
        use LWP::UserAgent;
        use Flickr::Upload qw(upload);

        my $ua = LWP::UserAgent->new;
        upload(
                $ua,
                'photo' => '/tmp/image.jpg',
                'email' => 'self@example.com',
                'password' => 'pr1vat3',
                'tags' => 'me myself eye',
                'is_public' => 1,
                'is_friend' => 1,
                'is_family' => 1
        ) or die "Failed to upload /tmp/image.jpg";

Flickr API を実装したPerlモジュール。 flickr_upload というスクリプトが含まれていて

flickr_upload --email <email> --password <password> 
                  [--title <title>]  [--description description] 
                  [--public <0|1>] [--friend <0|1>]

という感じで簡単にFlickrへ写真をアップロードできる。 パスワードやメールアドレスなどのオプションを $HOME/.flickrrc に設定を書いておけるってのも便利そう。

Berkeley DB で前方一致検索 (prefix search)

Berkeley DB はデータ構造として B木を扱える。 B木は、ハッシュと異なり、整列された順序で要素にアクセスできる点が特徴である。

PerlでBerkeleyDBって 1.x 用の DB_File 以外でつかった経験がなかったので Ruby + BerkeleyDB で書いた例をPerlで書いてみたのでメモ。

Maypole 2.0

| コメント(0)

Maypole - MVC web application framework

Simon Cozens さんから Sebastian Riedel さんにメンテナが引き継がれた Maypole - MVC web application framework の 2.0 が出てます。 CHANGESを読む限りではドキュメントを含めかなり整理整頓された感じ。

を。http://maypole.perl.org/とかできてる。

Bryar ではじめる blog (インストール、デザイン変更編)

blosxom 風の ブログ作成ツール Bryar のインストール方法と 生成されるHTMLのデザイン修正するためのTips。

BryarSimon Cozens さんによって書かれた blosxom 風のブログ作成ツールです。 Config, Frontend, Renderer, DataSource, Document, Comment, Collector とが モジュール化されていてそれぞれ独自の拡張が可能であるのと、 メインの部分は perl module としてインストールされるのが特徴です。 (Blosxom も 3.0 から Perl Module にとしての利用も考えた作りに なっているようですね。。)

以下でBryarを使ってブログを始めるための情報、 「インストール、デザイン変更編」を説明します。

インストール方法

  % sudo perl -MCPAN -e install Bryar

以上。

CPANモジュールのおかげでとっても簡単ですが、途中でいろいろと 「他のモジュールもインストールせい」とか言われるので [yes] と 答えておきましょう。インストールが無事終了し以下を実行してインストールした Bryarのバージョンが表示されれば ひとまずOKです。

  % perl -MBryar -e 'print $Bryar::VERSION,"\n"'
  2.6

次に、自分用のbryar.cgiを作成します。 ここでは /home/sekimura/blog ディレクトリを作成し、 そこにbryar.cgiやエントリーを設置することにします。

  % mkdir /home/sekimura/blog
  % cd /home/sekimura/blog
  % bryar-newblog

bryar-newblog は Bryar モジ ュールに含まれるツールで、ひとまず 始めるために必要なものを作成してくれるスターターキットです。 実行すると以下のようにファイルが作成されているはずです。

  % ls
  1.txt      bryar.conf  foot.html  template.atom  template.rss
  bryar.cgi  calendar    head.html  template.html

次にWebサーバ(ここではApache 1.3.X を使用)の設定で http://あなたのサーバ/blog が /home/sekimra/blog/bryar.cgi を指し示すようにします。 いろいろな方法がありますが、ここでは ScriptAlias を使った設定方法を例とします。

  ScriptAlias /blog "/home/sekimura/blog/bryar.cgi"

上記をhttpd.confに追加してhttpd を再起動しましょう。

デザイン修正

ひとまず動くようにはなりましたが、あまりに殺風景ですね。 早速、デザインを変えてみましょう。

まず、ブログの基本的な情報が記述されている bryar.conf を以下のように 修正します。

 name : 私のブログ。ほえー。
 description : ブログ界の第三世界ことBryarの情報など。
 baseurl : http://あなたのサーバ名/blog
 datadir : /home/sekimura/tmp

もう一度ブラウザで http://あなたのサーバ名/blog にアクセスしてみましょう。 name は <h1> タグで囲まれた文字列に反映され、 baseurl の修正によって # によるパーマリンクやカレンダーからの リンクが正しいものになっていると思います。

次にHTMLの修正を行なっていきます。 HTMLのレンダリングは(Bryarの拡 張性のおかげで、どうにでも変更できますが、 基本的に) Template-Toolkit を利用しています。ファイルは template.html です。 「MovableTypeみたいにCSS使ってゴニョゴニョ。」とか言う人は、まず template.html で呼び出されている head.html に CSS を呼び出す部分や <div class="banner"> とかを追加しましょう。各エントリーのHTMLは template.htmlにあるので 一生懸命 <p class="blosxomEntry"> とか書いているのを 直していきます。

(なんていう努力をしたくない人は MovableType風テンプレート を 用意したのでこちらを放り込んでください。 MoveableStyle.com から MovableType Rusty CSSなどCSSファイル持ってきて組み合わせれば、 似非MovableTypeが一丁出来上がりです。)

さあ、もう一度アクセスしてみましょう。 テンプレートの変更が反映されたページが表示されるはずです。

エントリーの追加

初級編の最後としてエントリーの追加方法を簡単に書いておきましょう。

さきほど作成した /home/sekimura/blog というディレクトリが bryar.conf で datadir となっていますので、このディレクトリ直下が エントリーを保存する場所になります。最初の状態では 1.txt というのがあり、それが最初のエントリーになっています。

エントリーを追加するには blosxom と同じように 2.txt や memo.txt といった *.txt のファイルを作成するだけです。 自動的にエントリーとして追加され、トップページへ反映されます。

その書き方は blosxom 形式で

  • そのファイルのタイムスタンプを日付とする
  • 最初の1行目がタイトル
  • それ以下の行が記事のHTML

となります。例えば

 % cat 2.txt
 私のはじめての投稿

 <p>おおブログ。<p/>

こんな感じのファイルを作成すると以下のようなエントリーが http://あなたのサーバ名/blog で表示されるページの上部に 追加され http://あなたのサーバ名/blog/id_2 や http://あなたのサーバ名/blog/2004/May/31 で アクセス可能になります。

About Me

このブログは Masayoshi Sekimura によって書かれています。現在はサンフランシスコ市内に在住し Six Apart, Ltd. でエンジニアをしています。 このブログ以外にオンラインでやっている事は qootas.org/sekimura/ で見ることができます。 メールは sekimura+blog@gmail.com までどうぞ。

このアーカイブについて

このページには、過去に書かれたブログ記事のうちPerlカテゴリに属しているものが含まれています。

前のカテゴリはMusicです。

次のカテゴリはPersonalです。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

ウェブページ

Powered by Movable Type 4.26