Diary?::2009-09

2009-09-03
Thu

(19:39)

今日のご飯はオムライス。「卵できちんと包めよ」という突っ込みに対しては、「これが俺のオムライスだ」ということで聞く耳持ちません。ちなみに昼間のうちに日記を書かなかったのは、間違って PC に写真をコピーする前にデジカメのデータを消しちゃったから。

じゃ、いつも通りレシピのコーナー。二食分の材料はこんな感じ。

  • ご飯:ご飯茶碗2杯分
  • 鶏胸肉:160g 前後。ってか食べたいだけ。あとどこの部位でもいい
  • ミックスベジタブル:食べたいだけ
  • 卵:1食あたり、1個か2個
  • サラダ油:大さじ1/2弱
  • 調味料:
    • ケチャップ:大さじ3杯かそこら。薄味になってもケチャップで調整可能だから気にしない
    • ウスターソース:大さじ1杯弱。こちらも調整可能なので気にしない
    • 塩コショウ:適量

作り方の手順は

  1. フライパンに油をひき、ミックスベジタブルと適度な大きさに切った鶏肉を炒める。ここで塩コショウを振ってもいい
  2. 鶏肉にある程度ご飯を混ぜてさらに炒め、調味料を投入。ケチャップとウスターソースは水で伸ばすと混ぜやすい
  3. フライパンに油をひき直し、卵を溶いて塩コショウで軽く味を付け、さっと卵を投入して半熟部分が残る程度に熱する
  4. チキンライスを盛り付け、そこに卵をのせてケチャップなりウスターソースなりをかけて出来上がり

とまあ、相変わらずテクニックのいらない一品。

2009-09-06
Sun

(00:48)

最近ちょっと仕事し過ぎであまり日記を書いていなかったので、久しぶりに軽めの Python ネタ。今回は Python で引数の型に応じたディスパッチ、というか普通オーバーロードと呼ばれることをやってみる。殆ど出オチのようなコードなので、解説は一切しない。

class Dispatcher(property):
    def __init__(self):
        property.__init__(self, lambda obj: lambda fst, *args, **kwds: self.execute(obj, fst, *args, **kwds))
        self.func_map = {}
    
    def __call__(self, t):
        if t in self.func_map:
            raise DispatchError(str(t))
        def _make_map(f):
            self.func_map[t] = f
            return f
        return _make_map
    
    def execute(self, obj, fst, *args, **kwds):
        fun = None
        for t, f in self.func_map.iteritems():
            if isinstance(fst, t):
                fun = f
                break
        if not fun:
            raise DispatchError('Can not dispatch to %s' % (str(t)))
        return fun(obj, fst, *args, **kwds)
    
class DispatchError(Exception):
    pass

使い方はこう。

class Foo(object):
    foo = Dispatcher()
    @foo(int)
    def ifoo(self, i):
        print '%d is integer' % i
    
    @foo(str)
    def sfoo(self, s):
        print '%s is string' % s

コードとしての見どころは property を継承しているところと、その property の getter としてλ式を渡し、そのλ式がディスパッチしたいメソッドの所属するオブジェクトを受け取り、そこからさらに Dispatcher の execute メソッドが呼ばれているところ。あとデコレータが None を返してるので個々の振り分け先のメソッドが隠蔽されてるところは、多分だけど実際には隠蔽しない方がいい。

だからどうしたという気がしなくもないが、思いついちゃったものは仕方がない。

(17:27)

そういや最近あんまりギターの練習もできてなかったなあと思ったので、リハビリがてら Paradise Lost の Shattered をコピーしてみた。リズムがよれてるのはいつもの事なので気にしない。ヴォーカルの出来が酷いのも(以下略)。本当はグロウルする曲じゃないんだけど、低音がどうしても出なかったのでごまかす事にした。いや、あんまごまかせてないけど。

ミキシングに関しては、ちょっとドラムが奥に引っ込みすぎた気がしないでもない。あとリードギターがやかましいかも。

2009-09-09
Wed

(01:30)

Caty プロジェクト全体の進捗については檜山さんのブログにあるとおりなので、今日はちょっと細かい成果物の公開でも。というかこれは Caty プロジェクトで開発したものではなく、俺が気分転換に書いたソフトウェアなのだが、何か使えそうなので Caty にバンドルする事にした(実際、既に Caty 内部では使われて始めてる)。

これは何かと言うとだな、 Python 用の文字列解析ライブラリだ。元ネタになったのは Haskell の Parsec なのだが、俺の作った奴はパーサコンビネータというわけでは全然ない。ただ、 Parsec みたいに宣言的にパーサを記述できるととても嬉しいので、ある程度は宣言的に書けるようにしたつもりだ。例えばサンプル代わりに同梱されている電卓のパーサはこう。

from topdown import *
from operator import *

def num(seq):
    e = seq.parse(Regex('-?[0-9]+'))
    return int(e)

def op1(seq):
    e = seq.parse(list('+-'))
    if e == '+':
        o = add
    else:
        o = sub
    return lambda a, b: (o, a, b)

def op2(seq):
    e = seq.parse(list('*/'))
    if e == '*':
        o = mul
    else:
        o = div
    return lambda a, b: (o, a, b)

def factor(seq):
    def _factor(s):
        p1 = s.parse('(')
        e = expr(s)
        p2 = s.parse(')')
        return e
    return seq.parse([num, _factor])

term = chainl(factor, op2)
expr = chainl(term, op1)

ちなみに括弧による演算順序の指定まで含めた四則演算の構文は、 BNF っぽく書くとこう。

EXPR ::= EXPR '+'|'-' TERM | TERM
TERM ::= TERM '*'|'/' FACTOR | FACTOR
FACTOR ::= '(' EXPR ')' | NUMBER
NUMBER ::= '-' DIGIT | DIGIT
DIGIT ::= '0'|'1'|...

ただし、これは定義が左再帰になっているので、トップダウン構文解析では無限再帰に陥る事がある。というか、このライブラリだと陥る。なので、左再帰を除去する。ここでのεは空を表すものとする。また、 FACTOR 以下は先のものと同じ。

EXPR ::= TERM _EXPR
_EXPR ::= '+'|'-' TERM _EXPR | ε
TERM ::= FACTOR _TERM
_TERM ::= '*'|'/' FACTOR _TERM | ε

ただしこのまま素直に展開すると演算子が右結合になってしまって具合が悪いんで、もうちょっと考える必要がある。

ちなみにこの四則演算というのはつまり、

  1. EXPR は TERM と加減算の演算子が交互に現れるリストを結合したもの
  2. TERM は FACTOR と乗除算の演算子が交互に現れるリストを結合したもの

といっていい。先のサンプルコードで言うと、

term = chainl(factor, op2)
expr = chainl(term, op1)

の部分がほぼそれだ。また、他の関数も大体定義どおりに実装できている。

実際これはちょっと都合の良すぎる例で、例えば同梱してる creole 文法のパーサはパフォーマンスチューニングのためにかなり汚い書き方になっている。一方で同じく同梱してる超簡易テンプレートエンジンはかなりファイル冒頭の嘘BNFに近い形でパーサが書けているので、まずは直観的にパーサを書き下してみて、パフォーマンス上の問題が出てきたら適宜力技でパーサを書き換えていくというのが良さそうである。

ちなみにドキュメントは何一つとして書いていないので、俺以外の人間が扱える代物かどうかは不明。先に書いたとおり Parsec とは最終的に全然別物になったので、そっちの知識があってもそこまで役に立つとは思えないし。

2009-09-16
Wed

(00:21)

一週間も日記の更新が滞るとか俺にとっては前代未聞なんだが、ちょっとこの一週間程は極めてデッドリーな仕様の追加変更に対応していたので日記とか書いてる場合じゃなかった。

それはともかくこの前晒した Paradise Lost の Shattered だが、あれの録音にはこれまで使っていた Zoom のエフェクターは使ってない。じゃあ何を使っていたのかというと、これだ。

実売価格が6万円オーバー、ギターと大体値段が一緒というかなり高い買い物だったが、こいつは本当に凄い。何が凄いって音がとても良いし、そのバリエーションも豊富。詳しいことは商品のページとかサンプル音源で確かめて欲しいが、ギターのアンプモデルを大量に揃えているのに加えてベースのアンプモデルもそれなりに揃えてあり、さらにはヴォーカル用のプリアンプまであるんだからな(Shattered ではプリアンプに Low-Fi を選んで高域をバッサリとカットしたセッティングで歌録りした。というかヴォーカルにもファズとかワウが普通にかかるのでかなり遊べそう)。ちなみに Live じゃない方の X3 も収録してるアンプモデルなどは一緒で、 Live 固有の機能は要らないって人はそっちの方が安くていいかもしれない。

で、さらにこの POD シリーズは MIDI 入出力端子が付いていて、やろうと思えば自作のソフトウェアからプリセットの切り替えやパラメータの制御もできるっぽい。というわけで、オフィシャルのマニュアルWriting Audio Applications With JACK を元にちょこちょこと調べ物をしたりコードを書いたりしてる。まあ、本当に何かを作るかどうかはまだわからんが。

2009-09-17
Thu

(12:50)

一昨日あたりに麻婆豆腐を作ったときにニラが余ったので、今日はニラ玉のようなものを作った。材料は以下の通り。

  • 豚バラ肉:150g(ちょっと多かった)
  • ニラ:適当
  • 卵:2個(3個ぐらい使った方が良かったが、2個しか残ってなかったんで)
  • 調味料
    • 醤油:50ccもあれば十分かも。今回はもっと多く使ったが、塩っ辛くなった
    • 水:200ccぐらいか?
    • みりん:適当

後はまあ、豚バラを煮込んでからニラを入れて、ニラに火が通ったら溶き卵を投入。卵が固まったら出来上がり。というか余り物を適当に組み合わせただけなので分量のバランスが極めて悪い。そのうちちゃんと作ってみるか。

2009-09-18
Fri

(17:04)

Python でマルチバイト文字列を扱うための Tips として sitecustomize.py でデフォルトのエンコーディングを指定しろというものがある。これは Python のライブラリパスの通ってるところに sitecustomize.py というファイルを置き、

import sys
sys.setdefaultencoding('...')

とやるというものだが、これをやるとプログラムが自分の環境に依存してしまうのでよくない。というか、かなりの間これに気がつかずに Caty の開発を進めていて、檜山さんからのバグレポでようやく気がついたという割とトホホな事がついさっきあった。

そういや UTF-8 の冗長表現によるセキュリティ問題についてだが、まず前提として Python は文字列(ってかバイト列)を Unicode にするときに冗長表現の UTF-8 はエラーにして叩き落とすようになっている。なので、外部から入力されたデータに対しては Unicode を適切な場所で使うことで問題はなくなる。そして

  • Caty は文字列をすべて Unicode に変換する
  • ユーザが書くプログラムには必ずスキーマを付け、そこで扱うデータの型を宣言する
  • スキーマを宣言しないと、どうやってもデータを受け取れない
    • 例えばフォームから foo という名前で文字列を受け取る場合、 {"foo": string} のような JSON スキーマが必須
    • 文字列ではなくバイト列として扱いたい場合、 binary 型で宣言しないとダメ
      • ちなみに binary 型の戻り値を string 型の引数を取る処理に渡すと、今のところ自動で Unicode に変換してる。理想を言えば型エラーなのだが、それやるには型推論と検証を実装しないとダメな事が発覚した(any 型とか型変数へ対応する必要性が発覚した)のでペンディング

という仕様になっているので、うっかり Unicode に変換せずに文字列を通してしまってバグやらセキュリティホールを作り込むという事態にはなりにくくなっている。流石に文字列が必要なところに binary を指定するミスは、うっかり Unicode に変換忘れよりは頻度は大きく少ないだろう。

あと Caty のテンプレートエンジンは VM レベルで特殊文字のエスケープを行うようにしている。これはエスケープ用の命令があるわけではなく、テンプレートに埋め込む情報の出力命令がエスケープ処理を行っているということ。テンプレートエンジンのフロントエンド(文法)はいくらでも追加可能だが最終的に吐き出されるコードの処理系は共通なので、やはり原理的に XSS などの脆弱性は作り込みにくくしてある。

まだ構想段階なのも含め、かなり Caty はいろんな仕様を安全側に倒すようにしてある。もっとも、最初のリリースでどこまでできるかは未知数だが。

2009-09-20
Sun

(14:54)

ここ最近は食指の動くタイトルがパッケージでは全然発表されてなかったんだが、反面 DSi ウェアではなかなか楽しめたゲームがあった。とりあえず特に面白かった奴を二本ほどピックアップ。

ARIKA と任天堂のタッグによる弾幕シューティング。タイプ A の機体を選べばクリアするのは難しくなく、ぶっちゃけ切り返しが多少できれば初見でクリアも難しくない。タイプ B だとかなり難度が上昇するが、それでも他の弾幕シューティングよりは良心的な気がする。まあ、俺はへたれなのでタイプ A でばかり遊んでるが。

そしてどちらの機体でもスコアアタックが非常に熱く、インターネットランキングのトップスコアラーのプレイは必見だ。また、インターネットランキングへの接続にはパッケージソフトのように WEP でないと接続できないという事もない。諸事情により WPA でしか無線 LAN 環境を作る気のない俺にとってはありがたい。

なんか元は iPhone で出たゲームらしいが、詳しいことは知らん。一応これレースゲームなんだけど、競技種目に「ライバル車を一定数クラッシュ」「レース中に稼いだ金額が多ければ勝ち(金を稼ぐ=ライバルやパトカーをクラッシュさせる)」というものがある事から予想できる通り、精密なコース取りが要求されるようなゲームではない。マシンのチューニングも適当でいいし、深く考えずにプレイできる。あとは人を轢き殺せればなお良かったんだが。

2009-09-22
Tue

(23:45)

料理日記を書こうにも全然新しいレシピを開拓してないので書きようがない。なので、今日は俺の手持ちの料理本についてのレビューを書く。いや、レビューといえるほどのものじゃないんだが。

俺が手元に持ってる料理の本は決定版 はじめての料理という本なのだが、こいつはただの一点によって糞本だ。その一点とは、食材・レシピともに五十音順の索引がないこと。マジでそれだけで微妙なところで使い勝手が悪くなっている。野菜の切り方のレクチャーとか参考になる部分が結構あるし、何より俺の普段作ってる料理はこの本のレシピの翻案というか簡易化のようなものが結構あるので世話になってるには違いないんだが、だからこそ余計イライラする。

この本では「ごはん・だし」「野菜」「肉」などという大分類の中に小分類があるという章立てなのだが、このやり方はリファレンス的に本を使おうとするときにはまったく向いてない。「にんじんの拍子切りってどうやるんだっけ」と思ったときに、容易に頭出しできないのはストレスだ。というかそもそも「分類」という行為自体が非合理的・恣意的な要素を排除するのが大変なので、逃げの一手かもしれないけど五十音順の索引を付けてくれよ。

2009-09-23
Wed

(10:37)

もんのすげえゲーム少年だったという押切蓮介のエッセイ漫画みたいなもの。ゲームにハマりすぎたせいで女の子と疎遠になったり、学業に無茶無茶悪い影響が出たり、不良連中に怯えながらゲーセンに通ったりといったエピソードが作者特有のユーモアで料理されて繰り出される一冊。

ギャルゲー・エロゲーが云々といったエピソードにはあんまり共感するものがなかったが(俺そういうゲームやらねえからなあ)、それ以外のエピソード、特に駄菓子屋の50円ゲーセンの話なんかは俺も昔は良くそういう所に通っていたりしたんで、やたらと懐かしい感じがしたなあ。

単純に押切蓮介の漫画が好きなら十分面白く読めると思うけど、ゲーム&ウォッチ〜ファミコン/スーファミ〜プレステ/サターンという家庭用ゲーム機の変遷が直撃だった世代には特にお勧め。

それにしても「勉強もスポーツもできない俺でも格ゲーなら○○連勝の腕前」とかのエピソードは、なんかいわゆる「ネトゲ(MMORPG)廃人」の出現にも絡んできそうな話だったな。というか、ゲーセンで凄いプレイをしてギャラリーの注目を浴びるのもネトゲで超レア装備とレベルカンストして他のプレイヤーから羨望の眼差しで見られるのも、ゲームを通じた自己顕示欲の充足という点では変わらないはずだよな。それでもどういうわけか問題の深刻度はネトゲ廃人の方がでかそうに思えるんだが、俺はネトゲというか MMORPG を一切やったことないんでイマイチ実感がない。というわけで、それっぽそうな記事へのリンクを張ってお茶を濁しとく。

「誰でもできる」「ゲームの尺がやたら長い」といったあたりが、特に廃人を生み出す原因なのかなと。

2009-09-25
Fri

(23:54)

ふと11月あたりまでに発売されるゲームのラインナップをチェックしてみたら、こんなのが。

……いや、これマジで買ってしまいそう。ぶっちゃけ悪い予感しかないけど、なんかもうムーミンというだけですべてを許してしまいそうな俺がいる。

2009-09-28
Mon

(23:32)

この土日は毎年恒例(?)の胃腸炎でへばり気味だった。何でか知らんが、毎年のようにウィルス性の胃腸炎にかかるんだが、毎年のように二日ほどくたばって治るというパターン。多分、「軽めの風邪→でも胃腸に来ると大惨事」というのだろうと思うが。

というわけで今日は生存報告して終わり。

2009-09-30
Wed

(19:27)

というわけでようやく最初のバージョンが公開されたので、こっちの方でも告知 & いくつかのお知らせ。こちらは檜山さんの考えていることではなくて、あくまでも俺が現在考えていること、一応檜山さんに提案していることなどが中心。

まずこのバージョンはほぼ人柱版だと考えてもらって差し支えなく、全体的にコードの記述は荒い。とりあえず全体的な方向付けは大体見えてきたので、これらは順次リファクタリングしていく予定。特に Caty の実装に関わる方向付けが不明瞭なまま書き始めた mafs 関連のモジュールや、真っ先にとりあえず書いたテンプレートエンジンはかなり凄いことになってる。いや、他の部分も大概だが、それらは特に。

テンプレートの他に JSON スキーマやスクリプトなど、全体的に構文解析が多いのだが、それを antlr で構文解析していたり俺の書いた topdown ライブラリで構文解析していたり、イマイチ統一性に欠けている部分がなきにしもあらずなので、もしかしたら今後は統一してしまうかもしれない。そもそも諸事情により Caty は antlr2 系統で開発を始めたのだが、これを antlr3 に移植する手間と topdown で書き直す手間じゃ、メンテナンスコスト含めて後者の方が低くなりそうだ。まあ、あくまでもこれは実装詳細なので、 Caty 上で作業する上ではあまり関係がない。

今現在 Caty で使えるストレージはぶっちゃけ素のファイルしかなく、それはいくらなんでもあんまりなので、近いうちに JSON データベースを追加する予定。というか自分でデモサイトを作ってる最中に「JSON データベースがねえとダメだ」と思ったので、これは俺の中では優先度高め。

それと JSON 自体も普通のバイト列がないのはちょっとどうかと思うので、なんかバイナリデータを持てるようにしてみたい。試験的に JSON パーサを Python 2.6 以降の標準ライブラリの奴(simplejson)とコンパチになるように書いてみたところ、実のところほとんど苦労せずに生のバイト列を JSON に埋め込めそうに思えた。これは本当にどうしようか考え中で、標準ライブラリにあるものと殆ど同じもの載せてもなあとか、むしろ base64 あたりの形式に変換して JSON スキーマで頑張ってコンバートできないかとか、まあいろいろ思案してる。

というわけで機能強化や仕様変更その他諸々、やっぱり俺の頭上には死兆星が6つぐらい輝いているので、俺と同程度の技量の持ち主でニートやってる奴は部屋と手料理と小遣いやるからしばらく俺の手伝いしてみないか。

どういうオチだ。

(20:19)

PS3 で出る Wiz 新作が嫌な予感しかしない。まあ、俺が買う予定なのは DS 版なのだが、こっちはこっちでいろいろキナ臭い。

……マジでどうすっかな。もうそこそこキャラの育成とダンジョン探索が楽しめて、適度に歯応えがあればいいや程度の気持ちでいた方が良さそうな気がする。