« February 2008 | Main | April 2008 »

March 2008

31 March 2008

TypePad エンジニアも募集しています。

シックス・アパートの求人のページで、住職の募集とありますが、住職じゃないけどシックス・アパートのプロダクトに興味のある開発者も募集しております。お経もいいけど TypePad もね。

シックス・アパート的にはコードが書ける住職がベストですね。

住職の方の主な業務内容は以下の通りだそうです。さすが外資系は違いますね。

主な業務内容

* 毎日の坐禅において社員にカツを入れる
* 週1回の全社ミーティングで法話を語る
* 年に2回のお盆イベントを主催する
* 定期的に読経を行う
* shakyou-a-thonを主催する

26 March 2008

Hash::Merge

Perl でハッシュをマージしたいなと思った。というか Catalyst で config メソッドはどうなっているのか見てみたら、Catalyst::Component の config メソッドで Catalyst::Utils::merge_hashes を呼び出している。merge_hashes($a, $b) としたときに、$a に $b をマージするためにいろいろとごにょごにょしているわけです。そのごにょごにょ(つまり Catalyst::Utils::merge_hashes)を単体で使いたいと思ったけど Catalyst 名前空間のモジュールは依存関係に含めるとちょっと厄介なイメージがあったので、単体で使えるモジュールが CPAN にないか探してみたらありました。

Hash::Merge

名前からしてズバリな感じです。

使い方は perldoc にあるように次の通り。

use Hash::Merge qw( merge );my %a = (    'foo'  => 1,    'bar'  => [ qw( a b e ) ],    'querty' => { 'bob' => 'alice' },);my %b = (    'foo'  => 2,    'bar'  => [ qw(c d) ],    'querty' => { 'ted' => 'margeret' },);

my %c = %{ merge( \%a, \%b ) };

とすると、デフォルトでは %a から %b に上書きする感じになって結果は次のようになります。

$VAR1 = 'bar';$VAR2 = [     'a',     'b',     'e',     'c',     'd'    ];$VAR3 = 'querty';$VAR4 = {     'bob' => 'alice',     'ted' => 'margeret'    };$VAR5 = 'foo';$VAR6 = 1;

ARRAYは結合してくれているし、SCALARは上書きしてくれているし、HASHはマージしてくれている。

で merge メソッドの第二引数を第一引数にかぶせたい場合もあるでしょう。そんなときには Hash::Merge::set_behavior メソッドを使います。
先ほどの上記のコードは以下のようになります。

use Hash::Merge qw( merge );my %a = (    'foo'  => 1,    'bar'  => [ qw( a b e ) ],    'querty' => { 'bob' => 'alice' },);my %b = (    'foo'  => 2,    'bar'  => [ qw(c d) ],    'querty' => { 'ted' => 'margeret' },);

Hash::Merge::set_behavior( 'RIGHT_PRECEDENT' );
my %c = %{ merge( \%a, \%b ) };

とすると結果は次の通りです。

$VAR1 = 'bar';$VAR2 = [     'a',     'b',     'e',     'c',     'd'    ];$VAR3 = 'querty';$VAR4 = {     'bob' => 'alice',     'ted' => 'margeret'    };$VAR5 = 'foo';$VAR6 = 2;

SCALAR である foo が %b の方を採用して 2 になっているのがわかりますね。

merge メソッドの引数の書き方を見れば分かるようにハッシュのリファレンスを渡していますし、merge メソッドの戻り値もハッシュのリファレンスなので次のように書く事もできます。

my $a = {    'foo'  => 1,};my $b = {    'foo'  => 2,};my $c = merge( $a, $b );

そうすれば結果は以下のようにになりますね。

$VAR1 = {     'bar' => [           'a',           'b',           'e',           'c',           'd'          ],     'querty' => {            'bob' => 'alice',            'ted' => 'margeret'           },     'foo' => 2    };

これはいい。Hash::Mergeを採用してみることに決めました。

25 March 2008

花見

桜が少しずつ花を咲かせていますが、我々のオフィスのみんなと花見に行く計画があります。楽しみです。

23 March 2008

多摩動物園

多摩動物園に行ってきました。広くて一日ではまわりきれないですね。ライオンバスはおすすめです。ライオンがえさを食べる姿を目の前で見ることができます。これはとても興味深いです。
それから今日はコアラの機嫌がよかったのかわるかったのかコアラが木から降りて床を歩き回っていました。こんな姿はなかなか見られないですね。
いやー楽しかったです。また行こうと思います。

Continue reading »

21 March 2008

テストです。

This is a test. please ignore this entry. thanks.

19 March 2008

xs:choice

今、XML Schema について少し学んでいるのですが、xs:choice について疑問があって調べました。

xs:choice というのは以下の例の場合、foo, bar, baz のいずれか一つを選択しなければなりません。

<xs:choice>  <xs:element name="foo" />  <xs:element name="bar" />  <xs:element name="baz" /></xs:choice>

xs:choice には 2 つの属性があります。

  • minOccurs (デフォルトは1)
  • maxOccurs (デフォルトは1)

なので、<xs:choice minOccurs="1" maxOccurs="1"> ということになるわけです。でも省略されているから、<xs:choice> は必ず一つを選択するということです。
で、<xs:choice minOccurs="0"> とした場合は 1 つ含まれるかもしれないということになるので、選択してもいいし選択しなくてもよくなります。(具体的にはmaxOccurs="1"なので、0か1ということです。)

<xs:choice minOccurs="0">  <xs:element name="foo" />  <xs:element name="bar" />  <xs:element name="baz" /></xs:choice>

foo, bar, baz のうちの1つあるかないかってことですね。

で、当初悩んでいたのが、次の例です。

<xs:choice minOccurs="0" maxOccurs="unbounded">  <xs:element name="foo" />  <xs:element name="bar" />  <xs:element name="baz" /></xs:choice>

unbounded は無制限の意味になります。ではこのときfoo, bar, baz はいくつ選ぶことができるか?
foo, bar, baz の 3 つでも OK ですし、それこそ foo, foo, bar, bar, bar, baz でも OK らしいです。もう choice の意味がないんじゃないか?と思う程。むしろ、xs:choice をやめて以下のようにしてもいいんじゃないか?と思ったり。(おそらく xs:choice にする意味がどこかにあるからこそ、xs:choice を使っているのだと思いますが。。。)

  <xs:element name="foo" minOccurs="0" maxOccurs="unbounded" />  <xs:element name="bar" minOccurs="0" maxOccurs="unbounded" />  <xs:element name="baz" minOccurs="0" maxOccurs="unbounded" />

ま、私は今のところ XML Schema を書くのではなく読む側なので、<xs:choice minOccurs="0" maxOccurs="unbounded"> の意味さえ分かればそれで OK なのですが、それにしても XML Schema は自由すぎて不自由な感じがしました。

ちなみに RelaxNG で書くと以下になります。

( foo | bar | baz )*

ところで、W3C の XML Schema の和訳ってなにげに少ないんですね。。。


参考

15 March 2008

テスト

soccerテストです。 please ignore this entry.baseball

春ですね。

今日はとても暖かい。こんな日はうたた寝をしてしまいそうです。

花粉

今年は花粉が多くて嫌ですね。まったく大変です。

13 March 2008

Google Contacts Data API

Google Contacts Data API を使った Movable Type のプラグインを実装しようと思っていたのですが、ブログにユーザ増やしたところであんまり意味が見いだせなくてプラグインの実装はちょっとペンディングなんですが、でもせっかく Contacts Data API を使ったのでサンプルをのせておきます。

今回のポイントは Simon WistowNet::Google::AuthSub です。GData API 系で必ず使う認証の ClientLogin をラップしてくれます。ClientLogin が成功すると Google から戻って来た値をほんの少しごにょっとしなきゃならないのですが、それを隠蔽してくれるので少しきれいなコードになりますね。

このコードを実行するとメールアドレスのリストが取れます。

#!/usr/local/bin/perl

use strict;
use warnings;

use LWP::UserAgent;
use HTTP::Request::Common;
use Net::Google::AuthSub;
use XML::LibXML;
use Data::Dumper;

my $user = 'YOUR_EMAIL_ADDRESS';
my $password = 'YOUR_PASSWORD';
my $authsub = Net::Google::AuthSub->new(service => 'cp');
my $auth_res = $authsub->login($user, $password);
unless ($auth_res->is_success) {
die 'google login is failed.'
}

my $url = "http://www.google.com/m8/feeds/contacts/$user/base";

my $req = HTTP::Request->new(GET => $url);
$req->header($authsub->auth_params);
my $res = LWP::UserAgent->new->request($req);

my $xp = XML::LibXML->new;
my $xml = $xp->parse_string($res->content);
my @emails = $xml->findnodes("/*[local-name()='feed']/*[local-name()='entry']/*[local-name()='email']");
for my $mail (@emails) {
print $mail->findvalue('@address') . "\n";
}

Access Ranking

Powered by Six Apart
Sponsored links