世界線航跡蔵

Mad web programmerのYuguiが技術ネタや日々のあれこれをお送りします。

2008年01月13日

ファーストクラスオブジェクトとしてのメソッド

Rubyと高階関数:

関数そのものがファーストクラスではない

やー、Rubyのメソッドはファーストクラスですよ。返り値にできて、変数に格納して演算できて、引数にできるという意味では。

確かに、RubyはPythonやJavaScriptやSchemeに比べると高階関数を陽に使うプログラミング*1は不格好になる。Pythonなら簡単なのに、

bound_function = obj.hoge
bound_function(arg1, arg2, arg3)

Rubyは余計なメソッド呼び出しがくっついて不格好だ。

method = obj.method(:hoge)
method.call(arg1, arg2, arg3)

私もこの点が気にくわなくてまつもとさんに「メソッドがファーストクラスだったらいいのに」と言ったことがある。でも、まつもとさんの考えではすでにファーストクラスということだった。

名前空間

もう細かいところは記憶が定かでないので、以下は私の理解になる。メソッドはただ、名前空間が違うんだ。

既存のメソッドと同名の識別子に値を代入すると、それはローカル変数の初期化になる。けれども、メソッド呼び出しでは依然として元のメソッドを参照する。

p = 1
p p #=> 1

変数の名前空間とメソッドの名前空間は別だ。メソッド呼び出しではメソッドの空間を規定の順序で探索する。値の代入では変数の名前空間を探索する。値の参照においては、ローカル変数をまず探して、存在しなければ引数を持たないメソッドとみなして探索する。

メソッドの名前空間にあるものは呼び出すことができる。変数の名前空間にあるものは呼び出すことができない。ただ、変数の名前空間にあるものに対しては「メソッドを呼ぶ」ことはできる。だから、メソッドあるいはそれに類するものには「それがメソッドの名前空間にあるかのように呼び出す」というcallメソッドが備わっている。

メソッドObject#methodはメソッドの名前空間からメソッドを取り出して、変数の名前空間に持ってくるメソッドだ。一方、Module#define_methodは逆操作をする。

Rubyの選択

私としてはScheme方式のほうが格好いいとは思う。Rubyの名前空間分離方式っていうのはCommon Lispから継承した代物だよね。たぶん。いや、CL以前のLispのどれかかもしれないけど。

でも、名前空間を一緒くたにすると「selfを省略可能」「引数の括弧を省略可能」というのは難しくなってしまう。Rubyとしては、高階関数を綺麗に書けることよりもこれらのほうが重要だろうと判断しての選択だ、とまつもとさんは言っていた。Ruby 1.9では今のところは

proc.(arg1, arg2, arg3)

はできるようになっているけれども。この点についてはまつもとさんも苦心しているのが見えて、対案がないことにはどうも文句を言いづらい。

結論

というわけで、名前空間の違いですよー、と。


*1ご指摘の通り、暗に使うのがブロック構文ね


トラックバック

http://yugui.jp/articles/741/ping

現在のところトラックバックはありません

コメント

blog comments powered by Disqus

ご案内

前の記事
次の記事

タグ一覧

過去ログ

  1. 2016年07月
  2. 2016年01月
  3. 2015年09月
  4. 2015年08月
  5. 過去ログ一覧

フィード

フィードとは

その他

Powered by "rhianolethe" the blog system