<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
   <channel>
      <title>西尾泰和のブログ @ Cybozu Labs</title>
      <link>http://labs.cybozu.co.jp/blog/nishio/</link>
      <description></description>
      <language>ja</language>
      <copyright>Copyright 2009</copyright>
      <lastBuildDate>Thu, 20 Dec 2007 17:50:28 +0900</lastBuildDate>
      <generator>http://www.sixapart.com/movabletype/</generator>
      <docs>http://blogs.law.harvard.edu/tech/rss</docs> 

            <item>
         <title>Googleを使ってMD5を逆変換</title>
         <description><![CDATA[<a href="http://wordpress.rauru-block.org/index.php/1512">Rauru Blog » Blog Archive » MD5破りにGoogleを活用</a>という記事を見て、試してみました。
<pre>
>>> import md5
>>> md5.md5("Python")
<md5 HASH object @ 01493320>
>>> _.hexdigest()
'a7f5f35426b927411fc9231b56382173'
</pre>
確かに「a7f5f35426b927411fc9231b56382173」で検索してみるとPython関連のサイトがヒットしますね。
<p>
Pythonはまぁ蛇という意味で一般名詞としても使われるので「YRAV」で試してみたところこんなサイトが…：<a href="http://md5-db.com/hashes/YAR">The MD5 Collision Database: Starting with YAR</a>
<p>
「Python」の代わりに「Pyth0n」にしてみると何もヒットしませんでした。結局「十分長く」「辞書的単語でない」単語を使わなければ簡単に逆変換できてしまうと言うことですね。]]></description>
         <link>http://labs.cybozu.co.jp/blog/nishio/2007/12/googlemd5.html</link>
         <guid>http://labs.cybozu.co.jp/blog/nishio/2007/12/googlemd5.html</guid>
        
                  <category domain="http://www.sixapart.com/ns/types#tag">MD5</category>
                  <category domain="http://www.sixapart.com/ns/types#tag">Python</category>
        
         <pubDate>Thu, 20 Dec 2007 17:50:28 +0900</pubDate>
      </item>
            <item>
         <title>自分がBruteForceBlockerに引っかかってしまったときの対処</title>
         <description><![CDATA[<a href="http://ja.doukaku.org/">どう書く？org</a>では<a href="http://danger.rulez.sk/projects/bruteforceblocker/">BruteForceBlocker</a>
を使ってブルートフォース攻撃を仕掛けてくるIPアドレスからのパケットを捨ててしまうようにしているのですが、今日変なことをしていたら自分がブロック対象になってしまいましたorz
<p>
対処方法：
<ul>
<li>別のIPアドレスからログインする
<li>/var/db/ssh-bruteforceに記録されている自分のIPアドレスを削る(もしここにデータファイルがなければ、ps -xでbruteforcebrockerの場所を調べ、中を見て設定ファイルの位置を調べ、その設定ファイルを見ると書いてある)
<li>/etc/rc.d/pf restart でパケットフィルタを再起動する
</ul>
<p>
あんまり変なことをしないように気をつけないと…(^^;
]]></description>
         <link>http://labs.cybozu.co.jp/blog/nishio/2007/11/bruteforceblocker.html</link>
         <guid>http://labs.cybozu.co.jp/blog/nishio/2007/11/bruteforceblocker.html</guid>
        
        
         <pubDate>Mon, 26 Nov 2007 16:31:32 +0900</pubDate>
      </item>
            <item>
         <title>Python4JS and KEMURI Interperer on it</title>
         <description><![CDATA[<a href="http://d.hatena.ne.jp/yukoba/20071108/p1">OreScript時代の幕開け - yukobaの日記</a>はとても面白い。
<p>
ので、
<p>
Pythonで書かれている<a href="http://www.nishiohirokazu.org/blog/2006/09/kemuri.html">KEMURI</a>
のインタプリタを&lt;script type="text/python4js">で囲ってHTMLソースに書いておくと、それがJavaScriptに変換されて実行される、というデモを作ってみました。
<p>
<a href="http://www.nishiohirokazu.org/files/python4js/">Python4JS and KEMURI Interperer on it</a>
<p>
<p>
ラボでは他にも
<a href="http://labs.cybozu.co.jp/blog/nakatani/2007/11/jsruby.html">JSRuby - Javascript による Ruby(っぽい)実装 (nakatani @ cybozu labs)</a>
などが公開されていますが、僕のこのデモは深夜ノリで作ったため、Python2.5の全機能をサポートしているわけではありません。今後改良していく予定もありません。ごめんなさいごめんなさい。ソースコードを見て石を投げないで！]]></description>
         <link>http://labs.cybozu.co.jp/blog/nishio/2007/11/python4js_and_kemuri_interpere.html</link>
         <guid>http://labs.cybozu.co.jp/blog/nishio/2007/11/python4js_and_kemuri_interpere.html</guid>
        
                  <category domain="http://www.sixapart.com/ns/types#tag">JavaScript</category>
                  <category domain="http://www.sixapart.com/ns/types#tag">Python</category>
        
         <pubDate>Thu, 22 Nov 2007 14:11:37 +0900</pubDate>
      </item>
            <item>
         <title>大きなテーブルへのForeignKeyにはraw_id_admin=True</title>
         <description><![CDATA[<a href="http://ja.doukaku.org/">どう書くorg</a>は
<A href="http://www.djangoproject.jp/">Django</a>を使って作られていて、
下のような管理画面が
<p>
<img src="http://labs.cybozu.co.jp/blog/nishio/images/raw_id_1.png">
<p>
下のようなモデルの定義から自動的に生成されます。
<pre>
class Comment(models.Model):
    topic = models.ForeignKey("Topic", null=True, blank=True)
    parent = models.ForeignKey("self", null=True, blank=True)
    create_date = models.DateTimeField()
    author = models.ForeignKey(User, null=True)
    body = models.TextField(blank=True)
</pre>
<p>
すごく楽ちんだったのですが、どう書くorgがにぎわってコメント数が増えてくるに従って
どんどん重たくなってきました。
<p>
理由はとても簡単で、この自動生成されたリストの部分で、
数千件あるすべてのコメントをデータベースから取ってきて文字列にする処理が行われるからです。
<p>
<img src="http://labs.cybozu.co.jp/blog/nishio/images/raw_id_2.png">
<p>
↑数千件がリストの中に…
<p>
このせいでページを開くだけで30秒程度かかっていました。
この問題はどうすれば解決できるか。
実はすごく簡単で、フィールドの定義にrw_id_admin=Trueをつけるだけでした。
<pre>
-   parent = models.ForeignKey('self', null=True, blank=True)
+   parent = models.ForeignKey('self', null=True, blank=True, raw_id_admin=True)
</pre>
このオプションをつけるとすべてを読み込んでリスト表示する代わりに、
下のようなIDを入れる欄と虫眼鏡アイコンが表示されます。
<p>
<img src="http://labs.cybozu.co.jp/blog/nishio/images/raw_id_3.png">
<p>
虫眼鏡アイコンを選ぶとアイテムの一覧が別ウィンドウで開きます。
<p>
テーブルが大きくなってくるとリスト表示では探すのも面倒になるので、
大きくなりそうなテーブルへForeignKeyを張っているなら今のうちにraw_id_adminをつけておくのも手かもしれません。

]]></description>
         <link>http://labs.cybozu.co.jp/blog/nishio/2007/11/foreignkeyraw_id_admintrue.html</link>
         <guid>http://labs.cybozu.co.jp/blog/nishio/2007/11/foreignkeyraw_id_admintrue.html</guid>
        
                  <category domain="http://www.sixapart.com/ns/types#tag">Django</category>
                  <category domain="http://www.sixapart.com/ns/types#tag">Python</category>
        
         <pubDate>Mon, 12 Nov 2007 16:42:35 +0900</pubDate>
      </item>
            <item>
         <title>「どう書く？org」(ベータ版)を公開しました</title>
         <description><![CDATA[<a href="http://ja.doukaku.org/">どう書く？org</a>というサービスを公開しました。
<p>
どう書くorgについてオフィシャルに言及するのは初めてなのですが、
アルファ版の時点ではてなブックマークのホットエントリーになったり、
<a href="http://secure.ddo.jp/~kaku/tdiary/20070702.html">オレンジニュース</a>や
<a href="http://internet.watch.impress.co.jp/static/yajiuma/2007/07/05/">やじうまWatch</a>で言及していただいたりしたので
すでにご存じの方もいらっしゃるかもしれません。
そこでこの記事では今まで語ってこなかった「どうして『どう書くorg』を作ろうと考えたのか」について解説したいと思います。
<p>
そもそものきっかけは<a href="http://d.hatena.ne.jp/rubyco/20060530/mltfind">マルチリンガルなシソーラス検索 - rubyco（るびこ）の日記</a>でした。
言語Xを使っている人が新たに言語Yを使うときになにが障害になるか、というと、
やはり「言語Xでならどうやるか0.1秒で思いつくような簡単な内容を、
言語Yではドキュメントをひっかきまわして探さないといけない」というフラストレーションなわけです。
そのフラストレーションを避ける気持ちが、プログラマを「自分が一番慣れている言語」という檻に閉じこめるのです。
プログラミング言語間の対訳があれば、殻を破ってマルチリンガルの大空に羽ばたくことができるのに。
<p>
さて、この対訳マルチリンガル・クックブックを作る上で、
まずは「Wikipedia的なアプローチで言語間の対訳データが集められないか」
と考えPukiWikiで集積サイトを作りました。
しかし「これは絶対に盛り上がらない」と判断して公開しませんでした。
単なるWikiではコードを書いてもらうインセンティブに欠けると思いました。
<p>
その後、どういう流れがあったのかは正確には覚えていません。しかし、いつしか
<a href="http://ll.jus.or.jp/2006/blog/doukaku1">キミならどう書く 2.0 - ROUND 1 - Lightweight Language Ring</a>
のようなアプローチをもったいないと感じるようになりました。
お題に対してコードを書いている人のほとんどは、そのコードの再利用を禁止したいとは思っていないはずです。
なのに、許可を明示的に取らないせいで実質的に再利用できずに散逸させてしまっています。
せっかく無償でいろいろな言語のコードを書いてもらうことができているのに。これはとてももったいないことです。
<p>
このようにして「どう書くorg」の三本柱「マルチリンガル志向」「お題にチャレンジ」「再利用可能なライセンス」ができました。
みなさんのおかげで、7月頭にどう書くorgを公開してから今までの4ヶ月弱で、2796件のコードが投稿されています。
1日平均20件以上という計算になります。
<p>
今後の課題は、こうやって集まったコードをどう加工するかだと思います。
<a href="http://ja.doukaku.org/search/">指定したコード中から特定の文字列を検索して、同じお題の別の言語のコードを表示する機能</a>
を3ヶ月も前に実装したのですが、これは現状の「お題と解答」というシステムではコードの粒度が大きすぎてなかなか望み通りのものが得られません。
ソースコードを静的に解析することで使われているモジュールを推定する機能(<a href="http://ja.doukaku.org/lang/python/used_module/">どう書く？org Python 使用モジュール一覧</a>)
がついたので、次は「同じお題で使われることの多いモジュールは似た機能のモジュール」というような推定でしょうか。
それとも、お題にするには粒度が小さすぎるような内容を
<a href="http://ja.doukaku.org/74/nested/">文字列中のアルファベットを大文字にする どう書く？org</a>
のような公開トピックとしてどんどん作ることで粒度の小さいコードを増やすのがいいのでしょうか？
まだまだ先が見えません。
<p>
しかし、たとえどう書くorgプロジェクトが道半ばで頓挫しても、
集まった「自由に再利用できる」コードは他のプロジェクトの肥やしになるはずです。
進めるところまで進んでみるのが正解かな、と思っています。
<p>
長々と昔話や妄想を書きつづってきましたが、まとめたいと思います。
どう書くorgは今まで「出されたお題をいかに解くか競い合う、プログラマのためのコロシアム」と名乗っていました。しかし「プログラマのためのコロシアム」なのは手段であって目的ではありません。どう書くorgの目的は「マルチリンガル・クックブック」を自然発生させることなのです。
]]></description>
         <link>http://labs.cybozu.co.jp/blog/nishio/2007/10/doukakuorg.html</link>
         <guid>http://labs.cybozu.co.jp/blog/nishio/2007/10/doukakuorg.html</guid>
        
        
         <pubDate>Mon, 29 Oct 2007 21:37:04 +0900</pubDate>
      </item>
            <item>
         <title>Pythonで関数名を安全に変更する</title>
         <description><![CDATA[Pythonのような動的な言語では、Javaのように「メソッドの名前を呼び出しも含めて変更」というリファクタリングが簡単ではありません。整合性をチェックするフェーズがないので、不用意に名前を変更すると実行時に「そんな名前の関数はない」と怒られてしまいます。
<p>
そこで「一度deprecated(非推奨)にする」という方法を考えました。
<p>
まず下のようにfooという関数と、それを読んでいるcallerという関数を作りました。今からこのfooをbarという名前に変更したいと思います。
しかし、実際にはcallerは大量のソースの中に散らばっているものとします。
<pre>
>>> def foo():
	return 1

>>> def caller():
	return foo()

</pre>

fooの名前を変更します。ここではbar = fooとしていますが、もちろんdef foo...をdef bar...に書き換えるのでもOKです。実際は後者になるでしょう。
そして、fooという名前で改めて警告メッセージを出してbarを呼ぶ関数を定義します。
<pre>
>>> bar = foo
>>> def foo():
	import inspect
	print "'foo' is deprecated: called from", inspect.stack()[1][3]
	return bar()
</pre>
こうすると、うっかりcallerの中のfooの呼び出しをbarの呼び出しに変え忘れても：
<pre>
>>> caller()
'foo' is deprecated: called from caller
1
</pre>
変える値は変わらず、警告メッセージだけが表示されるようになります。警告は今はprintで出していますが、ログに出すなりなんなりするといいと思います。
<hr>
追記：
毎回こういうことを書くのも面倒なので関数にまとめました。
<pre>
>>> def deprecated(f):
	def deprecated_func(*args, **kw):
		import inspect
		print "'%s' is deprecated:" % f.func_name,
		print "line %s in '%s'" % tuple(inspect.stack()[1][2:4])
		return f(*args, **kw)
	return deprecated_func

>>> def nibai(x):
	return x * 2

>>> def foo():
	print nibai(10)
	print nibai(20)

	
>>> foo()
20
40
>>> nibai = deprecated(nibai)
>>> foo()
'nibai' is deprecated: line 2 in 'foo'
20
'nibai' is deprecated: line 3 in 'foo'
40
</pre>]]></description>
         <link>http://labs.cybozu.co.jp/blog/nishio/2007/10/python_3.html</link>
         <guid>http://labs.cybozu.co.jp/blog/nishio/2007/10/python_3.html</guid>
        
                  <category domain="http://www.sixapart.com/ns/types#tag">Python</category>
        
         <pubDate>Wed, 17 Oct 2007 12:55:38 +0900</pubDate>
      </item>
            <item>
         <title>Pythonの辞書をドットでアクセス</title>
         <description><![CDATA[Pythonの「辞書」はとても便利なデータ構造ですが、「x」というキーに関連づけられている値を取り出すのには「['x']」とキー以外に4文字も書かなければ行けなくて面倒です。
<pre>
>>> p = dict(x=1, y=2)
>>> p
{'y': 2, 'x': 1}
>>> p['x']
1
</pre>

JavaScriptみたいにp.xでアクセスできると便利です。
そこでp.xでアクセスできるようにする関数を作りました。

<pre>
>>> p = modulize(p)
>>> p.x
1
</pre>

実装はこちら：

<pre>
>>> def modulize(dictionary):
	import imp
	m = imp.new_module("")
	m.__dict__.update(dictionary)
	return m
</pre>

なお、modulizeの時点で辞書がコピーされているので、modulize済みのオブジェクトのメンバを書き換えても元の辞書は変化しません。

<pre>
>>> p = dict(x=1, y=2)
>>> p2 = modulize(p)
>>> p2.x = 100
>>> p
{'y': 2, 'x': 1}
</pre>

変更済みの辞書を取得するには下のように__dict__を使います…ってモジュールにしたせいで__doc__とかが勝手に追加されていますね…

<pre>
>>> p2.__dict__
{'y': 2, '__name__': '', '__doc__': None, 'x': 100}
</pre>

…すなおに下のように書いた方がいいかも。

<pre>
>>> class MyDict(dict):
	__getattr__ = dict.__getitem__
	__setattr__ = dict.__setitem__
	__delattr__ = dict.__delitem__

	
>>> MyDict()
{}
>>> d = _
>>> d.x = 1
>>> d
{'x': 1}
>>> d.x
1
>>> del d.x
>>> d
{}
</pre>]]></description>
         <link>http://labs.cybozu.co.jp/blog/nishio/2007/10/python_2.html</link>
         <guid>http://labs.cybozu.co.jp/blog/nishio/2007/10/python_2.html</guid>
        
                  <category domain="http://www.sixapart.com/ns/types#tag">Python</category>
        
         <pubDate>Tue, 16 Oct 2007 16:24:31 +0900</pubDate>
      </item>
            <item>
         <title>続：typoを素早く察知する方法</title>
         <description><![CDATA[先日公開した
<a href="http://labs.cybozu.co.jp/blog/nishio/2007/08/pythontypo.html">Pythonでtypoを素早く察知する方法</a>の続編です。
前回公開したものは
「codeオブジェクトを破壊的に書き換えるCodeHackモジュール」
を流用して作りましたが、typo察知にCで書かれたモジュールは必要ないので、
コードオブジェクトの解析部分だけを切り出してPure Pythonのモジュール
「Coda」を作成しました。
<p>
前回は
「関数を与えると、その関数を呼び出さずに、その関数が起こしそうなNameErrorを警告する」
というものでしたが、今回はモジュールとネストしたコードオブジェクトをサポートしました。
ファイル名を指定して、そのファイルが起こしそうなNameErrorを警告させることが可能です。
<p>
たとえば下のような内容のファイル(tests/test_target.py)があった場合に
<pre>
def some_func():
    pass

def foo():
    print some_finc()

</pre>

find_name_error.pyを実行すると下のように
「5行目のsome_fincは、それより外側のスコープでLOADされていないよ、typoじゃない？」
と表示されます。

<pre>
C:\Python25\Lib\site-packages>find_name_error.py coda\tests\test_target.py
line 5: some_finc
</pre>
<p>
使い方：まずScriptsフォルダに入っているfind_name_error.pyを
C:\Python25\Scriptsなどのパスの通っている場所に移動してください。
このとき、名前は適当に変更しても構いません。
<p>
適当なフォルダに移動して-hというオプションで起動してヘルプが出ればOKです。
<pre>
C:\>find_name_error.py -h
Usage: find_name_error.py [options]

Options:
  -h, --help            show this help message and exit
  -r DIR, --recursive=DIR
                        find *.py under the directory
  -w, --watch           watching target continuously(not implemented yet)
</pre>
表示されているヘルプが多少事実と異なりますが(直しておきます)、
引数にファイル名を与えるとそのファイルを、-rとフォルダ名を与えるとそのフォルダ以下の*.pyファイルを走査します。-wをつけるとファイルの更新を監視します。
<p>
ソースコードは共有リポジトリ
<a href="http://coderepos.org/share/">CodeRepos::Share</a>
で公開中です。
Subversionがインストール済みであれば、たとえば
下のようにしてPythonのsite-packages内でチェックアウトするだけでOKです。
<p>
C:\Python25\Lib\site-packages>svn co http://svn.coderepos.org/share/lang/python/coda/trunk/coda
<p>
Subversionを入れたくない人のために一応ZIPで圧縮したバージョンも置いておきます。
<p>
<a href="http://labs.cybozu.co.jp/blog/nishio/coda.zip">Coda rev 228</a>
<p>
既知の問題点はこちら：
<a href="http://coderepos.org/share/browser/lang/python/coda/trunk/PROBLEMS_JA.txt">/lang/python/coda/trunk/PROBLEMS_JA.txt - CodeRepos::Share - Trac</a>
<p>
鮎川さんからご指摘のあったユニコード文字列のstrでエラーになる件は、
使っているエンコーディングによってエラーになったりならなかったりするので、
近いうちにユーザがエンコーディングを指定できるようにします。]]></description>
         <link>http://labs.cybozu.co.jp/blog/nishio/2007/09/coda.html</link>
         <guid>http://labs.cybozu.co.jp/blog/nishio/2007/09/coda.html</guid>
        
                  <category domain="http://www.sixapart.com/ns/types#tag">Python</category>
        
         <pubDate>Wed, 19 Sep 2007 16:41:38 +0900</pubDate>
      </item>
            <item>
         <title>Pythonでtypoを素早く察知する方法</title>
         <description><![CDATA[先日「スクリプト言語は便利だけど、
長時間計算した後で綴り間違い(typo)で落ちたりすると
やる気がなくなるよね」
という話を聞きました。
たしかに、綴り間違いで落ちるのは悲しいです。
せめて「代入されたけども読み出されていない変数」とか
「代入される前に読み出されている変数」が出力できれば、
早めに綴り間違いに気づくことができますね。
<p>
そこで「先日公開した<a href="http://labs.cybozu.co.jp/blog/nishio/2007/06/codehack.html">CodeHack</a>モジュールを使えば簡単にできるよ」と言いながら作ったのが今回紹介するモジュールです。
<del>
<a href="http://pypi.python.org/pypi/CodeHack/0.05">CodeHack 0.05</a>に同梱しました。
</del>
<ins>
<a href="http://pypi.python.org/pypi/codehack/0.06">CodeHack 0.06</a>に同梱しました。
</ins>
<p>
使い方は簡単です。
たとえば下のような関数fooを定義したとします。
<pre>
def foo(left, top, right, bottom):
    "function for test"
    width = right - left
    hieght = top - botom
    print height, width
</pre>

よく見ると2カ所ほど綴り間違いがあるのですが、
この関数をcodehack.var_warningの中のcheckfuncに渡してみると
下のようにその綴り間違いの変数が表示されます。関数fooを<strong>実行していない</strong>ので、たとえ実行に1時間かかるような関数であってもチェックは一瞬です。

<pre>
>>> from codehack.var_warning import checkfunc
>>> checkfunc(foo)
variable 'botom' is global
variable 'height' is global
variable 'hieght' is not used
variable 'bottom' is not used
</pre>

実は綴り間違いの判定は何もしていなくて、
単純に「値が代入されたのに読み出されていない」
という変数を「not used」と表示しているだけです。
また、逆の「値が代入されていないのに読み出されている変数」は
Pythonでは「グローバル変数と見なして外のスコープを見に行く」
という仕様になっているのでglobalと表示しています。(注1)

<p>
ただ、そのままですと'range'や'set'なども警告されたり、
自分で定義したグローバル関数を使うとそれも警告されたり、
とうっとうしいことになるので、
警告しない名前のリストをsurpressという引数で指定できるようにしてあります。
デフォルトでは組み込みの名前(rangeとか)がsurpressに入っています。

<pre>
def checkfunc(func,
          print_globals = True,
          print_not_used = True,
          print_func_name = False,
          surpress = _default_surpress):
</pre>

<p>
CodeHackモジュールを使っている部分は、実はたいしたことはしていません。
下のようにLOAD_FAST(ローカル変数のロード)という
オペコードの引数(変数名になっている)を集めているだけです。
codehack.util.analyzeはオペコード間の依存関係(どのオペコードが積んだ値をどのオペコードが消費するか)のトレースをするのですが、それも必要ないのでわざわざ外しています。

<pre>
    import util
    opcodes = util.analyze(func, do_trace=False)

    loaded_vars = set(op.argstr
                for op in opcodes
                if op.opname == "LOAD_FAST")
</pre>

下のようにして、モジュールの中の全ての関数をチェックすることもできます。
すでに自分で書いたモジュールがあれば試してみると面白いでしょう。
checkallはprint_globalsをFalseにしてあるので「代入されているけど読み出されていない」変数だけが出ます。

<pre>
>>> from codehack.var_warning import checkfunc, checkall
>>> import urllib
>>> checkfunc(urllib.urlopen)
variable 'FancyURLopener' is global
variable '_urlopener' is global
>>> checkall(urllib.__dict__)
* function splitnport
* function getproxies
* function retrieve
variable 'msg' is not used
variable 'garbage' is not used
(snip)
</pre>

ぜひ試してみて、ご意見ご感想やパッチを頂けるとうれしいです。

<p>

(注1) 実際はもちろんグローバルの名前空間にいきなり行くわけではなくて、
スコープがネストしている場合には1枚外のスコープへ行きます。
globalと呼んでいるのは単にバイトコードがLOAD_GLOBALだからだったりします。
いい名称があれば変えたほうがいいかもしれません。
また、関数がネストしている場合は内側の関数で使われる変数を
「使われる」と判断することができずに警告を出してしまいます。
これはdisしてみるとわかるのですが、内側の関数はコードオブジェクトとして
定数テーブルに埋め込まれているため、
外側の関数のバイトコードを見ただけでは内側で何を使うかがわからない
ことが原因です。定数テーブルにコードオブジェクトがあるかどうかをチェックして
再帰的にたどるようにすればいいだろうと思いますが…それは今後の反響次第と言うことで。]]></description>
         <link>http://labs.cybozu.co.jp/blog/nishio/2007/08/pythontypo.html</link>
         <guid>http://labs.cybozu.co.jp/blog/nishio/2007/08/pythontypo.html</guid>
        
                  <category domain="http://www.sixapart.com/ns/types#tag">Python</category>
                  <category domain="http://www.sixapart.com/ns/types#tag">下を行け</category>
        
         <pubDate>Tue, 14 Aug 2007 15:00:54 +0900</pubDate>
      </item>
            <item>
         <title>Pythonコード添削道場</title>
         <description><![CDATA[来る6月30日、東大駒場キャンパスで<a href="http://www.python.jp/Zope/workshop/200706">Python Workshop the Edge 2007</a>が開催されます。
<p>
「Pythonコード添削道場」はこのワークショップのセッションの一つで、私、<a href="http://labs.cybozu.co.jp/blog/nishio/">西尾 泰和</a>と<a href="http://ymasuda.jp/">増田 泰さん</a>、<a href="http://coreblog.org/ats/">柴田 淳さん</a>の3人で投稿されたコードを添削するという企画です。
<p>
この企画はみなさんにコードを投稿して頂かないと始まりません。
コードの内容は自由なので、ぜひご投稿ください。
<p>
また「投稿してといわれても、ちょうどいいコードがないなぁ」
という人のために、お題が7つ用意してあります。
お題に挑戦してみて結果のコードを投稿するのもよいでしょう。
<p>
コードの投稿の際に名前を書く必要はありません。
完全に匿名でも、自分にしかわからないような
ハンドルネームでもOKです。
その方が添削する我々も、容赦なく添削ができます。
<p>
自分のコードが容赦なく添削される機会は、
そうそうあるもんじゃないですよ！
ぜひこのチャンスをものにして
理解を深めるきっかけにしてください。
<p>
お題は以下の7問です。
<ul>
 <li> お題１：ファイルの同期
 <li> お題２：単語数カウント
 <li> お題３：シングルトン
 <li> お題４：入れ子リストの中身を順に表示
 <li> お題５：行列の回転
 <li> お題６：名簿の並び替え
 <li> お題７：整数とビット列の相互変換
</ul>
詳細はこちらからどうぞ→<a href="http://www.nishiohirokazu.org/pwe2007/">Pythonコード添削道場</a>]]></description>
         <link>http://labs.cybozu.co.jp/blog/nishio/2007/06/python_1.html</link>
         <guid>http://labs.cybozu.co.jp/blog/nishio/2007/06/python_1.html</guid>
        
        
         <pubDate>Tue, 12 Jun 2007 12:05:21 +0900</pubDate>
      </item>
            <item>
         <title>PythonのバイトコードをGRINEditで可視化</title>
         <description><![CDATA[<img alt="pybc_vis5.PNG" src="http://labs.cybozu.co.jp/blog/nishio/images/pybc_vis5.PNG" width="1167" height="569" />

<p>
上の図は下のPythonで書かれた関数のバイトコードをGRINEditを使って可視化したものです。濃い青の矢印は「矢印先のインストラクションがスタックに積んだ値を矢印根本のインストラクションが消費した」という意味です。薄い水色の矢印はもうちょっと弱い「先が積んだ値を消費したわけじゃないけど、先がさわったスタックを根本もさわったか見た」という関係です。
赤矢印はジャンプです。
<p>
JUMP_IF_FALSEでの分岐で、条件式をポップせずに分岐して、分岐先の両方でいきなりポップしているのはなにか深遠な理由があるのでしょうかね？「JUMP_IF_FALSEは条件式をポップする」という仕様にすればelse節が省略されたときにポップするために4バイト使わないで済むのに。
<pre>
def facto(n, ans=1):
    if n == 0:
        return 1
    return facto(n - 1, n * ans)
</pre>
バイトコードは下のようになります。
<pre>
    0 7C_00_00 LOAD_FAST(n)
    3 64_01_00 LOAD_CONST(0)
    6 6A_02_00 COMPARE_OP(==)
    9 6F_08_00 JUMP_IF_FALSE() -> POP_TOP@20
   12       01 POP_TOP()
   13 64_02_00 LOAD_CONST(1)
   16       53 RETURN_VALUE()
   17 6E_01_00 JUMP_FORWARD() -> LOAD_GLOBAL@21
   20       01 POP_TOP()
   21 74_00_00 LOAD_GLOBAL(facto)
   24 7C_00_00 LOAD_FAST(n)
   27 64_02_00 LOAD_CONST(1)
   30       18 BINARY_SUBTRACT()
   31 7C_00_00 LOAD_FAST(n)
   34 7C_01_00 LOAD_FAST(ans)
   37       14 BINARY_MULTIPLY()
   38 83_02_00 CALL_FUNCTION()
   41       53 RETURN_VALUE() 
</pre>
<p>
いろいろ見ているとハッシュリテラルの作成に大量のROT_TWOが入っていたりとおもしろいです。どう考えてもSTORE_SUBSCRの仕様が間違っているようにしか思えません。
<p>
<img alt="pybc_vis6.PNG" src="http://labs.cybozu.co.jp/blog/nishio/images/pybc_vis6.PNG" width="1323" height="432" />
<p>
<pre>
def foo():
    {"a": 1, "b": 2, (1, 2): (1, 2)}
</pre>
<pre>
    0 68_00_00 BUILD_MAP() 
    3       04 DUP_TOP() 
    4 64_01_00 LOAD_CONST(1) 
    7       02 ROT_TWO() 
    8 64_02_00 LOAD_CONST(a) 
   11       3C STORE_SUBSCR() 
   12       04 DUP_TOP() 
   13 64_03_00 LOAD_CONST(2) 
   16       02 ROT_TWO() 
   17 64_04_00 LOAD_CONST(b) 
   20       3C STORE_SUBSCR() 
   21       04 DUP_TOP() 
   22 64_05_00 LOAD_CONST((1, 2)) 
   25       02 ROT_TWO() 
   26 64_06_00 LOAD_CONST((1, 2)) 
   29       3C STORE_SUBSCR() 
   30       01 POP_TOP() 
   31 64_00_00 LOAD_CONST(None) 
   34       53 RETURN_VALUE() 
</pre>

<p>
でもGRINEditの最新版をさっさと公開すべきですね、すみません。
GRINEditのドキュメントも書かないといけないですね。
このディスアセンブルや可視化のためのコードは先日<a href="http://labs.cybozu.co.jp/blog/nishio/2007/06/codehack.html">PyCodeObjectを書き換える</a>で紹介したCodeHackライブラリに入れました。そのうちにバージョン0.03で公開したいと思います。]]></description>
         <link>http://labs.cybozu.co.jp/blog/nishio/2007/06/pythongrinedit.html</link>
         <guid>http://labs.cybozu.co.jp/blog/nishio/2007/06/pythongrinedit.html</guid>
        
                  <category domain="http://www.sixapart.com/ns/types#tag">Python</category>
                  <category domain="http://www.sixapart.com/ns/types#tag">下を行け</category>
        
         <pubDate>Wed, 06 Jun 2007 22:20:49 +0900</pubDate>
      </item>
            <item>
         <title>Python拡張の作り方</title>
         <description><![CDATA[いくつかの落とし穴をよければ意外と簡単だったので、
この文章を必要としている誰かのために整理してみることにします。
<p>
追記：
<a href="http://d.hatena.ne.jp/earth2001y/20070611/p1">おびなたのはてな日記 - distutils with boost.python</a>で詳しく説明されているように、C++とBoostを使うともっと楽になるようです。近いうちに試してみます。
また、
<a href="http://cydn.cybozu.co.jp/files/python_survey_at_cydn.html">Cybozu Developer Network: Python調査報告 (2006/10)</a>
によれば
「PEAKの setuptools は distutils の拡張で(中略)distutils の上位互換であるため、setuptools を使用しない理由はありません。積極的に使用しましょう。」とのことなのでこちらも試してみたいと思います。

<h4>Cのコードを用意する</h4>

書き換えるべき所を明確にするために、
[[MODULE_NAME]]というように表記しました。
同じ名前の括弧には同じ文字列が入らなければいけません。
***と書いてある部分には、文脈にあわせて適切なことを書く必要があります。
<pre>
#include &lt;Python.h>

static PyObject *
[[FUNC_NAME]](PyObject *self, PyObject *args)
{
  ***; // 変数の宣言

  if (!PyArg_ParseTuple(args, ***)) //受け取る引数にあわせて書き換える
        return NULL;

  ***; // 肝心の処理

  Py_RETURN_NONE; //値を返さないでいい場合
  return Py_BuildValue(***); //返す場合
}

static PyMethodDef Methods[] = {
  {"[[PYTHON_FUNC_NAME]]", [[FUNC_NAME]], METH_VARARGS, "[[関数の説明]]"},
  {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC
init[[MODULE_NAME]](void)
{
  (void) Py_InitModule("[[MODULE_NAME]]", Methods);
} 
</pre>
<h4>setup.pyを作る</h4>

<pre>
from distutils.core import setup, Extension

module1 = Extension(
	'[[PACKAGE_NAME]].[[MODULE_NAME]]',
	sources = ['[[C_FILE_NAME]].c']
)

setup(
	name = '[[PACKAGE_NAME]]',
	version = '[[バージョン]]',
	description = '[[説明文]]',
	url = '[[URL]]',
	author = '[[NAME]]',
	author_email = '[[E-MAIL]]',
	ext_modules = [module1],
	packages=["[[PACKAGE_NAME]]"],
)
</pre>

PACKAGE_NAMEはPYTHON_MODULE_NAMEと同じでもかまいません。
Extensionの引数に「A.B」と指定した場合、
Aというフォルダの中にB.pydが生成されます。

<h4>パッケージを作る</h4>

[[PACKAGE_NAME]]と同じ名前のフォルダを作り、
そこに__init__.pyやテスト用のスクリプトなどを置きます。
この位置に置いたスクリプトは[[MODULE_NAME]].pydと同じフォルダにコピーされるので
import [[MODULE_NAME]]でインポートすることができます。
<p>
パッケージを作るようにsetup.pyを記述したので、
ここで__init__.pyを作成して最低限下のように書いておかないと
この後のリリースの時に困ります。
<pre>
import [[MODULE_NAME]]

__all__ = ["[[MODULE_NAME]]"]
</pre>
__init__.pyを作る手間が惜しければパッケージを指定しないで、
作成されたバイナリを手でパスの通ったところにコピーしても構いませんが、
あとで余計に手間がかかるかもしれません。

<h4>ビルド</h4>

コマンドプロンプトを立ち上げてsetup.pyのあるフォルダへ移動します。
基本的には「python setup.py build」でdistutilsがよしなに取りはからってくれます。
筆者の環境では「Cygwinでビルドするなら-c mingw32とつけろ」とメッセージが出るので
「python setup.py build -c mingw32」としました。
<p>
Cのコードに問題がある場合はここで表示されます。

<h4>テスト</h4>
buildフォルダの中(たとえばbuild\lib.win32-2.5\[[PACKAGE_NAME]])に
コンパイルされたバイナリと、その他のスクリプトがコピーされているはずです。
テスト用のスクリプトを起動して動作確認をします。
<p>
コンパイルされたモジュールを一度インポートすると、
そのインタプリタが生きている間は上書きに失敗するためコンパイルができません。
delでモジュールを消しても同様です。
Cのコードを書き換えてビルドし直す場合には忘れずにインタプリタを終了しましょう。

<h4>インストーラの作成</h4>

「python setup.py bdist_wininst」でウィンドウズ版のインストーラが作成されます。
しかし筆者の環境では「-c mingw32をつけろ」というエラーメッセージがが表示され、
言われたとおりにしてもエラーになります。
「python setup.py bdist_wininst --skip-build」
とやってビルドのプロセスを飛ばすのが正解です。

<h4>ソースリリースの作成</h4>

Windows用のインストーラだけでは他のOSを使っている人が困るので、
ソースリリースも作成します。
「python setup.py sdist」でOK、のはずですがなぜか
パッケージの中身の__init__.pyやtest.pyがコピーされなかったので手でコピーしました。
Windows用インストーラの方はきちんとコピーされているので謎です。

<h4>まとめ</h4>

何年か前にPythonの拡張ライブラリを作ろうとしたときには
gccでにどういうコンパイルオプションをつければPython.hへのパスが通るのか…
などと悩んだのですが、
distutilsを使うことでこんなに簡単にインストーラまでできてしまうことに驚きました。
ぜひ一度試してみることをおすすめします。]]></description>
         <link>http://labs.cybozu.co.jp/blog/nishio/2007/06/python.html</link>
         <guid>http://labs.cybozu.co.jp/blog/nishio/2007/06/python.html</guid>
        
                  <category domain="http://www.sixapart.com/ns/types#tag">C</category>
                  <category domain="http://www.sixapart.com/ns/types#tag">Python</category>
        
         <pubDate>Tue, 05 Jun 2007 19:41:51 +0900</pubDate>
      </item>
            <item>
         <title>PyCodeObjectを書き換える</title>
         <description><![CDATA[Pythonのcodeオブジェクトを書き換えてしまう拡張ライブラリ「CodeHack」を作りました。
下の使用例では、関数の中の加算命令を乗算命令に書き換えています。
<pre>
import CodeHack

def f(x):
        print x + 2

f(10) #-> 12

# replace ADD to MULTIPLY
code = f.func_code.co_code
code = code.replace("\x17", "\x14")
CodeHack.set_co_code(f.func_code, code)

f(10) #-> 20 
</pre>
<p>
Pythonの拡張ライブラリを作って公開するのも初めてですし、
C言語をさわるのも数年ぶりなのですが、
想像以上に簡単でした。
全部distutilsがやってくれるので、
コンパイラを自分で呼ぶ必要すらありませんでした。
see <a href="http://www.python.jp/doc/2.4/dist/dist.html">Python モジュールの配布</a>。
<h4>ダウンロード</h4> 
(22:31にバージョン0.02を公開しました。0.01はたまにPythonが異常終了します。)<p>
<a href="http://labs.cybozu.co.jp/blog/nishio/files/CodeHack-0.02.win32.exe">CodeHack-0.0.2.win32.exe</a>(Windows用インストーラ)
<p>
<a href="http://labs.cybozu.co.jp/blog/nishio/files/CodeHack-0.02.zip">CodeHack-0.02.zip</a>(ソースコード)

<h4>原理</h4> 
原理はとても簡単(原理と言うほどでもないくらい簡単)です。
コードオブジェクトのco_code属性はリードオンリーフラグが立っているためにPythonのプログラムで直接書き換えることはできませんが、
Cのコードから書き換えることは可能です。
そこで、コードオブジェクトと文字列を受け取って、co_codeを書き換えてしまうモジュールをCで書きました。
<pre>
#include &lt;Python.h>

static PyObject *
codehack(PyObject *self, PyObject *args)
{
  PyObject* c; // PyCodeObject
  PyObject* s; // PyString

  if (!PyArg_ParseTuple(args, "OO", &c, &s))
	return NULL;
  PyCodeObject* code = (PyCodeObject*) c;
  Py_INCREF(s);
  code->co_code = s;
  Py_RETURN_NONE;
}

static PyMethodDef Methods[] = {
  {"set_co_code", codehack, METH_VARARGS, "overwrite co_code"},
  {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC
initCodeHack(void)
{
  (void) Py_InitModule("CodeHack", Methods);
}
</pre>]]></description>
         <link>http://labs.cybozu.co.jp/blog/nishio/2007/06/codehack.html</link>
         <guid>http://labs.cybozu.co.jp/blog/nishio/2007/06/codehack.html</guid>
        
                  <category domain="http://www.sixapart.com/ns/types#tag">C</category>
                  <category domain="http://www.sixapart.com/ns/types#tag">Python</category>
                  <category domain="http://www.sixapart.com/ns/types#tag">下を行け</category>
        
         <pubDate>Tue, 05 Jun 2007 16:55:21 +0900</pubDate>
      </item>
            <item>
         <title>コーディング過程をLingrで中継</title>
         <description><![CDATA[<img alt="lingr.png" src="http://labs.cybozu.co.jp/blog/nishio/images/lingr.png" width="806" height="630" />
<p>
右半分がPythonの対話的インタプリタIdleで、左半分がチャットのLingrです。
対話的にコードを書いて試している過程がチャットでどんどん公開されていきます。
<p>
Lingrのボット(チャットを読み書きするプログラム)は
<a href="http://inforno.net/articles/2007/02/01/lingr-api-wrapper-for-python">inforno :: Python版Lingr APIライブラリ</a>
を使うと簡単に書けます。
リンク先の例では入退室と発言しかありませんが、
他人の発言をウォッチするのも
<a href="http://wiki.lingr.com/dev/show/UserObserve">User Observe in Lingr Developer Wiki</a>
を使うだけで簡単にできます。
<p>
しかし、Lingrにコードを書くのはオートインデントとかがなくて面倒なので、
対話的インタプリタの側からLingrに「実行する内容」と「実行した結果」を送信するようにしました。
チャットに書いたコードが自動的に実行されるとなるとセキュリティが心配ですが、
これは自分のマシンで走るのは自分の書いたコードだけなので安心です。
<p>
一番時間がかかったのは実は
「コンパイル時に"single"と指定すれば、与えられたコードが式である場合に評価した結果を表示するバイトコードが付加される」
と気づくところです。
ライブラリリファレンスの組み込み関数のところに書いてあるのに気がつかず、PyShell.pyを読みながら
「execはあるけども式かどうか判別するコードも評価した値を表示するコードもないぞ？」
と悩んでいたのでした。まさかバイトコードに入っているとは。
<p>
下のコードはまだ荒削りですが、
とりあえずこれで上図のような結果が出ます。
複数行のコードの場合、インデントがデフォルトでは表示されませんが、
これはLingrの方で「view paste」というリンクをクリックするときちんとインデントされます。
後は対話的インタプリタの評価のところでLingrと通信しているせいで反応が遅くなっていますが…
それは通信部分だけ別スレッドで動かすなどの解決方法がありそうです。
<p>
<pre>
import idlelib

from lingr import *
lingr = Lingr("***YOUR LINGR API KEY***")
lingr.api.session.create()
r = lingr.api.room
r.enter(id="***id***", nickname="***YOUR NICKNAME***", password="***YOUR PASSWORD***")

LOCALS = {}

class Tee(object):
	def __init__(self, stdout):
		self.buf = []
		self.stdout = stdout
	def write(self, s):
		self.buf.append(s)
		self.stdout.write(s)
		
import codeop
CC = codeop.CommandCompiler()

def wrap(f):
	def foo(self, s):
		result = f(self, s)
		if result == False:
			r.say(message = ">>> " + s + "\n\n")
			import sys
			sys.stdout = Tee(sys.stdout)
			exec CC(s, "single") in LOCALS
			r.say(message = "".join(sys.stdout.buf) + "\n" )
			sys.stdout = sys.stdout.stdout
		return result
	return foo

MI = idlelib.PyShell.ModifiedInterpreter
MI.runsource = wrap(MI.runsource)
idlelib.PyShell.main()
</pre>
<p>
追記：r.enter(id="***id***", nickname="***YOUR NICKNAME***", password="***YOUR PASSWORD***")のnicknameとpasswordはあなたのアカウントのものではなく、「ボットが名乗るてきとうなニックネーム」と「チャットルームのパスワード」です。テスト用にパスワードでアクセス制限をしたチャットルームを使っていたのでパスワードを指定していますが、普通のチャットルームなら必要ありません。
<p>
あとCommandCompilerを使わなくてもcompile(source, "&lt;string>", "single")でよさそうです。
]]></description>
         <link>http://labs.cybozu.co.jp/blog/nishio/2007/06/pythonlingr.html</link>
         <guid>http://labs.cybozu.co.jp/blog/nishio/2007/06/pythonlingr.html</guid>
        
                  <category domain="http://www.sixapart.com/ns/types#tag">Lingr</category>
                  <category domain="http://www.sixapart.com/ns/types#tag">Python</category>
        
         <pubDate>Mon, 04 Jun 2007 20:55:27 +0900</pubDate>
      </item>
            <item>
         <title>Javaでリストとかfor文とか</title>
         <description><![CDATA[どうも、Java勉強中の西尾です。
Javaって難しいですね…。
今日はようやくリストを作る方法を理解したので、
自分の勉強のためにまとめてみたいと思います。
普段Pythonの記事ばっかりなのでたまには気分を変えて。
<p>
Pythonでは「複数のオブジェクトが入った配列のようなオブジェクト」を下のような記法で作成できます。
<pre>
>>> xs = [1, 2, 3.14, "Hello!"] 
</pre>
JavaScriptやRubyでも同じで、Perlだと@xs = (1, 2, 3.14, "Hello")になるようです。
<p>
また、このオブジェクトの中身を順に表示するにはfor文を使います。
<pre>
>>> for x in xs:
        print x

        
1
2
3.14
Hello! 
</pre>
<p>

これと同じことをJavaではどう書けばいいのか、
今日やっと理解しました。
Javaでは下のようになります。
<pre>
Object[] xs = { 1, 2, 3.14, "Hello!" };
for (Object x : xs) {
        System.out.println(x);
}
</pre>
ただ、これではxsが配列なので、
Pythonでは下のように書ける「アイテムの追加」などができません。
<pre>
>>> xs = [1, 2, 3.14, "Hello!"]
>>> xs.append("Java")
>>> xs
[1, 2, 3.1400000000000001, 'Hello!', 'Java']
</pre>

アイテムの追加などが可能なオブジェクトにするために、
Collectionインターフェイスを実装したクラス
(<a href="http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/util/Collection.html">Collection (Java 2 Platform SE 5.0)</a>)
のオブジェクトを作りたいと思います。
それにはArrays.asListを使います。

<pre>
Vector&lt;Object> xs = new Vector&lt;Object>(Arrays.&lt;Object>asList(1, 2, 3.14, "Hello!"));
</pre>

Arrays.asListに配列を渡すと、List(これはCollectionの子インターフェイス)を
実装したクラス(Arrays$ArrayList)のオブジェクトを返してくれます。
なので下のように配列を渡しても上と同じことができます。
<pre>
Arrays.asList(new Object[]{ 1, 2, 3.14, "Hello!"})
</pre>

可変長引数でも渡せるので、実際に配列を作る必要はなく、
配列を作るための呪文「new Object[]{～}」が省けます。
ただしその場合「これらがObject型である」という情報が失われてしまうので、
それを補うために「Arrays.&lt;Object>asList」と指定しています。

<p>
さて、これでListを作るところまではできたのですが、
残念ながらここで作られるListのaddメソッドを呼ぶと、
「サポートされていない」という趣旨の例外が発生します。
(UnsupportedOperationException)
<p>
おそらく、配列をListに詰め替えているのではなく、
単にListに見えるラッパをかぶせているだけなのでしょう。
そこでVectorに詰め替えます。
VectorのコンストラクタにCollectionを渡した場合には、
中身の詰め替えが行われます。
正確に言うならば、仕様にはそういうことは書かれていない
(どころか、返ってくるリストがArraysのprivateなインナークラスなのでそもそも以下略)
のでソースコードを追うことになります。
Vectorのコンストラクタで、渡されたCollectionのtoArrayを呼ぶのですが、
Arrays$ArrayListのtoArrayは自分の持っている配列をcloneして返すので、
この時点で詰め替えが行われます。
<p>
さてこれで追加や削除ができるようになりました。
ここでクイズです。下のコードを実行するとどういう出力が出るでしょうか？
<pre>
Vector&lt;Object> xs = new Vector&lt;Object>(Arrays.&lt;Object>asList(1, 2, 3.14, "Hello!"));
xs.remove(3.14);
xs.remove(1);
xs.set(1, "newItem");
xs.add(1, 999);
xs.add("Java");
Collections.reverse(xs);
for (Object x : xs) {
        System.out.println(x);
}
</pre>
<p style = "margin-top: 5cm">
ヒント、Pythonで書くとこうなります。
</p>
<pre>
>>> xs = [1, 2, 3.14, "Hello!"]
>>> xs.remove(3.14)
>>> xs.pop(1)
2
>>> xs[1] = "newItem"
>>> xs.insert(1, 999)
>>> xs.append("Java")
>>> xs.reverse()
>>> for x in xs:
	print x
</pre>

<p style = "margin-top: 5cm;">
解答。
</p>
<pre>
Java
newItem
999
1
</pre>
出力結果に「1」が入っているのが意外です。
実はxs.remove(3.14);とxs.remove(1);ではremoveの意味が違い、
前者は「3.14という値を取り除く」のに対し、後者は「1番目の位置の値を取り除く」
になっています。
いやはや、Javaは<a href="http://0xcc.net/misc/bad-knowhow.html">奥が深い</a>ですね。
<p>
追記：
なぜこういう現象が起きるのかについて解説します。remove(int)とremove(Object)の両方のメソッドがあって、リテラルの1は(過去の諸々のしがらみによって)int型なのでremove(1)はremove(int)が呼ばます。一方リテラルの3.14はオートボクシングでObjectになるのでremove(Object)の側が呼ばれます。もしremove(Object)で1を削除したければ
明示的にxs.remove(new Integer(1));と書く必要があります。
<p>
ご指摘どうもありがとうございます＞<a href="http://d.hatena.ne.jp/jbking/20070605/re_java">Yのほぼコード置場 - Re:Javaでリストとか(ry</a>]]></description>
         <link>http://labs.cybozu.co.jp/blog/nishio/2007/05/javafor.html</link>
         <guid>http://labs.cybozu.co.jp/blog/nishio/2007/05/javafor.html</guid>
        
                  <category domain="http://www.sixapart.com/ns/types#tag">Java</category>
        
         <pubDate>Thu, 31 May 2007 21:14:41 +0900</pubDate>
      </item>
      
   </channel>
</rss>

