原です。

|正木です。

||Sequence.new(list){"|x| f(x)"}
||
||Sequence.new(list){"|t| f(t)"}
||で違う結果を得る可能性がありますよね。
|
|これは無いとおもいます。

これは一般的な話になってしまうのですが、例えばブロックの値の2倍を得よ
うとして

def foo
   x = 2
   eval(yield) * x
end

という関数がを作ったとき、うっかり

foo { "x = 100001; x * x" }

などとした場合、意図しない動作をしますよね。


|ローカル変数の scope についてまだ誤解しているといけませんので
|確認させてください。
|
|#その変数がブロック開始以前に未定義ならば
|#スコープがブロック内部に限られる。
|#定義されていれば
|#変数のスコープはブロック内部に限られない。

正しいと思います。


|これをうっかりして随分痛い目に会いました。
|main で block を使うと ローカル変数がある意味で大域変数になり得ると
|いうことなので、このことに気付いてから main の context の中では
|できるだけ block を使わない事にしています。
|変数の scope がそれ以前の code を全部調べないと分からないというのは
|困りませんか?

それは神経質過ぎます。(^^; ものは考えようで、同一スコープ内で変数の値
を変化させたくなければ、その変数に代入しないのは当たり前だとも言えます。
つまり、

   x = 0
   ...
   foo { x = 1 }
   ...
   p x

というのは、

   x = 0
   ...
   x = 1
   ...
   p x

というのとあまり変わらないわけです。なまじ前者の場合、代入が実際に行わ
れない場合もあるので、かえって危険な気持ちにさせているのかもしれません。

外部の変数の値を不変にするには、ブロックの中でも代入しないように気をつ
けるだけです。事がローカルに決定されるという点で大域変数のような不安は
ありません。もちろん、ブロックパラメータも代入式と考える必要があります。


|とは言っても initialize に渡した block はどこで評価されるかわからない
|ので、そのための苦肉の策が文字列だったわけです。文字列ならどこで評価
|されても変わりませんから。

こちらの方はブロックでその変数を使用して良いかどうかローカルに決定でき
ません。もし foo がライブラリの関数であれば、そのソースコードを調べる
必要が出てきてしまいます。それが eval を避けたい理由の一つです。


|しかし一方では
|# method 定義の中ではローカル変数は、本当に local

メソッドの中だから、トップレベルだから、という違いは特にないでしょう。
メソッドの中でもローカル変数を延々と使い回せば状況はわかりにくくなるし、
メソッドの中で他のメソッドにブロックを渡せばやはり同様な問題は生じるわ
けだから。