Diary?::2006-01-31

04:49

俺と似たようなことを考えている人がいたよ。もっとも、俺は全然違う実装をしているのだけどね。

以下は俺が実装した関数の部分適用と関数合成のコード。

def partial(f, *args, **kwds):
	count = f.func_code.co_argcount
	def func(*fargs, **fkwds):
		newkey = kwds.copy()
		newkey.update(fkwds)
		argv = args+fargs
		argc = len(argv)+len(newkey.keys())
		if argc == count:
			return f(*argv, **newkey)
		elif argc < count:
			return partial(f, *argv, **newkey)
		else:
			raise TypeError('%s takes exactly %d arguments (%d given)' % (f.func_name, count, argc))
	func.func_name = f.func_name
	return func

def compose(*funcs):
	l = len(funcs)
	assert l != 0
	if l == 1: return funcs[0]
	def do(*args, **kwds):
		r = funcs[0](*args, **kwds)
		for i in funcs[1:]:
			r = i(r)
		return r
	return do

部分適用は前に書いた奴よりもずっと素直なコードになったと思う。あとこの関数合成は一般的に認識されている奴とは違うな。名前変えるか。

12:52

うーわ、今朝書いた関数中身が一ヶ所ずつ間違ってるよ。

partial
args+fargs を fargs+args と書いていた。引数が逆順になっちまうって。
compose
funcs を反転イテレータにしないとダメじゃん。

一応直しておいた (使う奴がいるとは思えないが)。

14:02

言語ごとの流儀について。

例えば Haskell では、畳み込み演算は次のように書く。

foldl f first seq
foldl1 f seq

これに対して Python では次のようになる。

reduce(f, seq, frist)
reduce(f, seq)

初期値の指定箇所が入れ替わっていること、初期値をシーケンスの最初の要素とする場合でも同じ関数が使えることが Python と Haskell の違いだ。これに基づいて scanl を Python で実装する場合、 reduce と同様に初期値は第三引数として渡して、それが指定されなかったらシーケンスの最初の要素を使うというのがいいのではないかと。いや、むしろ Python では foldr に相当するものがないのだから、 scanl ではなく scan と した方が Python らしい。かもしれない。

俺が思うに、ある言語を使うためにはその言語の流儀に従わなければいけない。それが一見して納得できない物であっても、無用な混乱を招くよりはずっとましだろう。一貫性というのはどんな時でも重要だ。

22:02

ブログサービスの業者に文句をいいたい。過去ログの全文検索ぐらい付けやがれ (リソースが厳しいのなら仕方ないかもしれないけど)。特にカテゴリをサポートしていない場合なんか、全文検索が無いとまったくの手掛かり無しに過去ログを漁る必要があるわけで、そんなことしてられるかという話。

23:18

座っていて背中が痛くなるのは姿勢が悪いせいに違いない。というわけで椅子の上で正座してみたが、キーボードが打ちにくい。これはダメだ。

ところで Yahoo の crawler が /SlurpConfirm404/gpi/10.htm とかの実在しないファイルを取得しようとしてエラーになってんだけど、何やってんだ Yahoo は。

Written by Kuwata Chikara
Creative Commons