Webを眺めてたら、ふとしたことから前の会社でやってたプロジェクトの報告書に行き当たる。 懐かしい。
1997年に前の会社を辞めてるから、この報告書は私が辞めてから書かれたものだよな。 実はこのGPMEの一部にはRubyが組み込まれていたのだが、今となっては誰が知るだろうか。
というか、この時の成果っていったい今どうなってるんだろう。 全然使われていないような気がするんだけど。だとしたら、もったいない。オープンソースにしておけば。
RedHandedから。
このページを作ったArmin Roehrlは、自著である 「Programmieren mit Ruby」 (ISBN 3-89864-151-1)で、各章ごとにやたら面白い引用を付けていた(献本されたのを眺めてて、そこだけは英語だったので分かった)のだが、こんなページを持っていたとは。
私の言葉が結構載っている。こんな面白いこと書いたっけか(自画自賛)。 いずれにせよユーモアは重要だよな。
ブラジルからメールをもらう。 要約すると
というような内容。どうやら、
Ruby is a complete, full, pure object oriented language: OOL. This means all data in Ruby is an object, not in the sense of Python or Perl, but in the sense of Smalltalk: no exceptions. Example: In Ruby, the number 1 is an instance of class Fixnum.
という内容がブラジルのPythonエバンジェリストのお気に召さなかったらしい。 この文章を書いた時点では確かにそうだったんだけど、 そういえばnew style classとかが導入された時に、整数とかも含めてすべての「オブジェクト」はなんらかのクラスの「インスタンス」になったんだっけか。
で、調べてみる。やはり実際にPythonを起動するのがよいだろう。 irb相当が直接実行できるのは便利だ。
# python Python 2.3.4 (#2, Jan 5 2005, 08:24:51) [GCC 3.3.5 (Debian 1:3.3.5-5)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> type(1) <type 'int'> >>> int <type 'int'> >>> class Int(int): ... pass ... >>> Int() 0 >>> Int(256) 256 >>> type(Int(256)) <class '__main__.Int'>
確かに。ちゃんとintのサブクラスも作れる。じゃあ、intクラスにはどんなメソッドがあるのだろう。 確かPythonはdocstringがついてるって自慢してたな。
>>> print int.__doc__ int(x[, base]) -> integer Convert a string or number to an integer, if possible. A floating point argument will be truncated towards zero (this does not include a string representation of a floating point number!) When converting a string, use the optional base. It is an error to supply a base when converting a non-string. If the argument is outside the integer range a long object will be returned instead.
あれれ、変換関数のドキュメントだよ。おかしいな。
では、リフレクションを使って確認しよう。
>>> int.__dict__ <dictproxy object at 0xb7e2944c> >>> int.__dict__.keys <built-in method keys of dictproxy object at 0xb7e29464>
うーむ、わからない。ループを回せばよいのかな。
>>> for i in int.__dict__.keys: ... print i ... Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: iteration over non-sequence
だめだ。結局、ソースを読んで確認した(ここでドキュメントを探さないところがアレだけど)、 <type 'int'>(クラス)には唯一 __getnewargs__ というメソッドがあるらしい。
>>> 1.__getnewargs__() File "<stdin>", line 1 1.__getnewargs__() ^ SyntaxError: invalid syntax
あらら、そうか。「1.」は構文解析できないのか。
>>> (1).__getnewargs__() (1,)
これはたぶんシリアライズかなにかに使うんだろうな。 うーむ、勝手が違って使いにくい。
あ、riに対応するpydocってプログラムがあるんだっけ。
% pydoc int Help on class int in module __builtin__: class int(object) | int(x[, base]) -> integer | | Convert a string or number to an integer, if possible. A floating point | argument will be truncated towards zero (this does not include a string | representation of a floating point number!) When converting a string, use | the optional base. It is an error to supply a base when converting a | non-string. If the argument is outside the integer range a long object | will be returned instead. | | Methods defined here: | | __abs__(...) | x.__abs__() <==> abs(x) | | __add__(...) | x.__add__(y) <==> x+y | | __and__(...) | x.__and__(y) <==> x&y | | __cmp__(...) | x.__cmp__(y) <==> cmp(x,y) | | __coerce__(...) | x.__coerce__(y) <==> coerce(x, y) | | __div__(...) | x.__div__(y) <==> x/y | | __divmod__(...) | x.__divmod__(y) <==> xdivmod(x, y)y | | __float__(...) | x.__float__() <==> float(x) | | __floordiv__(...) | x.__floordiv__(y) <==> x//y | | __getattribute__(...) | x.__getattribute__('name') <==> x.name | | __getnewargs__(...) | | __hash__(...) | x.__hash__() <==> hash(x) | | __hex__(...) | x.__hex__() <==> hex(x) | | __int__(...) | x.__int__() <==> int(x) | | __invert__(...) | x.__invert__() <==> ~x | | __long__(...) | x.__long__() <==> long(x) | | __lshift__(...) | x.__lshift__(y) <==> x<<y | | __mod__(...) | x.__mod__(y) <==> x%y | | __mul__(...) | x.__mul__(y) <==> x*y | | __neg__(...) | x.__neg__() <==> -x | | __nonzero__(...) | x.__nonzero__() <==> x != 0 | | __oct__(...) | x.__oct__() <==> oct(x) | | __or__(...) | x.__or__(y) <==> x|y | | __pos__(...) | x.__pos__() <==> +x | | __pow__(...) | x.__pow__(y[, z]) <==> pow(x, y[, z]) | | __radd__(...) | x.__radd__(y) <==> y+x | | __rand__(...) | x.__rand__(y) <==> y&x | | __rdiv__(...) | x.__rdiv__(y) <==> y/x | | __rdivmod__(...) | x.__rdivmod__(y) <==> ydivmod(y, x)x | | __repr__(...) | x.__repr__() <==> repr(x) | | __rfloordiv__(...) | x.__rfloordiv__(y) <==> y//x | | __rlshift__(...) | x.__rlshift__(y) <==> y<<x | | __rmod__(...) | x.__rmod__(y) <==> y%x | | __rmul__(...) | x.__rmul__(y) <==> y*x | | __ror__(...) | x.__ror__(y) <==> y|x | | __rpow__(...) | y.__rpow__(x[, z]) <==> pow(x, y[, z]) | | __rrshift__(...) | x.__rrshift__(y) <==> y>>x | | __rshift__(...) | x.__rshift__(y) <==> x>>y | | __rsub__(...) | x.__rsub__(y) <==> y-x | | __rtruediv__(...) | x.__rtruediv__(y) <==> y/x | | __rxor__(...) | x.__rxor__(y) <==> y^x | | __str__(...) | x.__str__() <==> str(x) | | __sub__(...) | x.__sub__(y) <==> x-y | | __truediv__(...) | x.__truediv__(y) <==> x/y | | __xor__(...) | x.__xor__(y) <==> x^y | | ---------------------------------------------------------------------- | Data and other attributes defined here: | | __new__ = <built-in method __new__ of type object> | T.__new__(S, ...) -> a new object with type S, a subtype of T
なるほど。勉強になった。やたら、「__」が目立つけど、演算子がメソッドとして実装されているのね。 いつのまにか。ソースではどこに対応するんだろう。 ただ、他にはまったくメソッドが定義されていないので、 事実上「インスタンス」としては使えないなあ。 今まで通りの「オブジェクト」とさして変わりはないような気がする。
ま、少なくとも
ということは明らかになったわけだ。件のページは修正するか。
分かったこと。私はやっぱりPythonに向いてない。 いや、Pythonがわるいってわけではなく、ただ私の脳があまりにもRubyに染まり過ぎているということなのだが(当たり前か)。
ちなみに、上記と同じことをRubyで調べようと思えば
% irb irb(main):001:0> 1.methods => ["%", "between?", "send", ...略...] irb(main):002:0> 1.class.instance_methods => ["%", "between?", "send", ...略...] irb(main):003:0> Fixnum.instance_methods => ["%", "between?", "send", ...略...]
などの方法で直接的に調べられるし、あるいはriを使って
% ri Fixnum ------------------------------------------------ Class: Fixnum < Integer A +Fixnum+ holds +Integer+ values that can be represented in a native machine word (minus 1 bit). If any operation on a +Fixnum+ exceeds this range, the value is automatically converted to a +Bignum+. +Fixnum+ objects have immediate value. This means that when they are assigned or passed as parameters, the actual object is passed, rather than a reference to that object. Assignment does not alias +Fixnum+ objects. There is effectively only one +Fixnum+ object instance for any given integer value, so, for example, you cannot add a singleton method to a +Fixnum+. ------------------------------------------------------------------------ Includes: --------- Precision(prec, prec_f, prec_i) Class methods: -------------- induced_from Instance methods: ----------------- %, &, *, **, +, -, -@, /, <, <<, <=, <=>, ==, >, >=, >>, [], ^, abs, div, divmod, id2name, modulo, quo, size, to_f, to_s, to_sym, zero?, |, ~
としてもよい。
なんと。しかし、母集団が男子200名しかないので、1位でも8人。 ほんとに意味があるのか。統計学的にはどんなもんなんでしょう。