作者: Yukihiro Matsumoto
日時: 2004/3/13(09:42)
まつもと ゆきひろです

In message "[TSruby:133] Rubyのlambda"
    on 04/03/13, "機械伯爵" <kikwai@...> writes:

| でもコレって、Pythonのlambdaとえらく雰囲気違いま
|すね・・・

それはPythonのlambdaが違うんだと思います。

| 例えばPythonだと、lambdaを用いて階乗計算(すみま
|せんPythonブースの使いまわしです)を・・・
|
|f = lambda x:(x and f(x-1)*x)or 1
|
| とか書けるんですが、Rubyだとブロックの中からreturn
|できませんから、lambdaを使ってこういう書き方は想定さ
|れていませんね(まぁ、Pythonでもあまり推奨されていな
|い書き方ですし・・・)

想定されてないとおっしゃいますが、ちゃんと

f = lambda{|x|(x > 0 and f.call(x-1)*x)or 1}

と書けますし、想定内だと思います。。違いはlambdaで作った関数
を呼ぶ時にcallメソッドを使わなければならない点と、0は偽でな
い点ですから、本質的ではないと思います。

むしろ、RubyにはPythonのように「lambda本体は式でなければなら
ない」という限定がありませんから、andやorを使った不自然な記
述をしなくても

f = lambda{|x|if x == 0 then 1 else x*f.call(x-1) end}

または

f = lambda{|x|x == 0 ? 1 : x*f.call(x-1)}

と書けます。また、Rubyは1.8からlambda内でreturnが使えますか
ら、書きたければ

f = lambda{|x|if x == 0 then return 1 else return x*f.call(x-1) end}

でもOKです。このケースでは意味ないかもしれませんが。ですから、
「returnが使えない」のはPythonの方ですね。returnは文ですから
Pythonのlambda内では使えませんよね。いや、「returnできない」
というのは違う意味だったとは思いますが。

| まぁ、オブジェクトフィールドを直接外から操作でき
|たり、

instance_evalを使えば外から操作できます。Pythonに比べて面倒
なのはわざとです。

|def function():
|  return 100
|
|class Class:
|  pass
|
|x = function, Class
|a, b = x[0](), x[1]()
|
| みたいに、関数名はおろかクラス名まで無造作にオブ
|ジェクトとして放り込んで使ったりするあたりは、

これもできます。Rubyでもクラスはオブジェクトですから。ただ、
Pythonと違ってfunctionとclassが両方callableというわけではな
いので、見かけは違うでしょうけど。

| ただ、ソレがあるプログラミング環境に自分の思考が
|慣れきっているため、少しリハビリする必要があるよう
|です。

「Pythonが好き」とか「Pythonに慣れている」とか「移行は面倒」
というのはどれも理解できるのですが、事実に基づかないことで貶
めるのはフェアじゃないと思います。

RubyはPythonと違うし、欠点と感じられることもあるとは思います。
それはそれで構わないのですが、しかし、「できない」と断言する
前にちょっと考えていただけるとよいのではないかと思います。

                                まつもと ゆきひろ /:|)