Pythonで「へー」と思ったいくつかのこととRubyとの比較

集合知プログラミングのコードはpythonで書かれている。で、多言語で同じことをやろうとするとpythonの「へー」というところがいくつかあったので、まとめてみます。

勘違いがありまくると思いますが、指摘してもらえるとうれしいです。pythonはもう1年以上やってないし、やってた時もあんまり分かってない時だったので。

Pythonは関数型言語

関数型言語がどういうものか(というのの概要)を理解したのはつい最近なので、あれなんですが関数型言語らしいということに驚きました。関数がオブジェクトとして扱えて、その関数オブジェクトを直感的に呼び出すことができるというのにちょっとびっくりしました。例があったほうが分かりやすいので、例をば。

まず、hogeという関数を用意する。引数をそのまま返す関数。

>>> def hoge(a):
...     return a
...

これを引数なしで評価すると、関数オブジェクトが返ってくる!!とりあえずびっくりした点一個目。

>>> hoge
<function hoge at 0x65230>

もう一個びっくりした点。関数オブジェクトをそのまま関数の引数に渡せて、"スムーズに"呼び出せるということ。fugaという関数オブジェクトを受け取り、"aa"というのを適用した結果を返す関数を定義した。

>>> def fuga(a):
...     return a("aa")
... 
>>> fuga(hoge)
'aa'
>>>

こんな感じで、ふつーに呼び出せてしまった。

「え、ふつーに呼び出せるのがふつーじゃないの?」とか思ってしまったりするんだけど、Rubyだと案外うまくいかなかった。Rubyで関数を引数なしで呼ぶとエラーになって、関数オブジェクトを返してくれない。

>> def hoge(a)
>>   return a
>> end
=> nil
>> hoge
ArgumentError: wrong number of arguments (0 for 1)
	from (irb):4:in `hoge'
	from (irb):4

関数オブジェクトを返したい場合はこんな感じにする。hogeはObjectクラスのメソッドでもあるので、こんな感じで呼ぶ。時前で定義したクラスとかなら、そこを適宜変更する。

>> Object.method(:hoge)
=> #<Method: Class(Object)#hoge>

関数オブジェクトというかメソッドというクラスのインスタンスが返ってきた。これを呼び出そう!いっけー!

>> Object.method(:hoge)("a")
SyntaxError: compile error
(irb):23: syntax error, unexpected '(', expecting $end
Object.method(:hoge)("a")
                     ^
	from (irb):23
	from :0

がーん。callを使って明示的に呼び出してあげないといけないようです。これはしょんぼりしていまう。

>> Object.method(:hoge).call("a")
=> "a"

Rubyの例を見るとPythonは超自然な感じでできるんだなー、というのが分かった。まあ、集合知プログラミングではpythonで書かれているので、Rubyに移植するときはその辺で困るという(ry。

ちなみにlambdaを使うと、Procクラスのインスタンスを返してくれるけど(関数のところでは似たようなことだとエラーが出てた)、呼び出しはこっちもcallを明示的に使わないといけない。

>> lambda{|x|x}
=> #<Proc:0x01121320@(irb):25>
>> lambda{|x|x}("a")
SyntaxError: compile error
(irb):26: syntax error, unexpected '(', expecting $end
lambda{|x|x}("a")
             ^
	from (irb):26
	from :0
>> lambda{|x|x}.call("a")
=> "a"

もっと簡単な方法でできるのかもしれませんが、僕が頑張った感じだとこういうところまででしたー。

その他

気が向いたら書く。

  • deep copyについて
  • 関数内関数で外側の関数の引数を内側から呼べるかどうか
  • リスト内記法
  • タブルの意義