From: keiju@... (=?ISO-2022-JP?B?GyRCQFBETTc9PHkbKEI=?= ) Date: 1998-04-05T17:17:25+09:00 Subject: [ruby-dev:2062] Re: [Req] Binding.new けいじゅ@日本ラショナルソフトウェアです. In [ruby-dev :2055 ] the message: "[ruby-dev:2055] Re: [Req] Binding.new ", on Apr/03 19:27(JST) Yukihiro Matsumoto writes: >まつもと ゆきひろです >あー,普通は「インタラクティブでも独立した環境は必須じゃない >んだ」という結論がでると思うんですけど.^^;;; うーん. と思ったら... ># ちなみに動的スコープはこの問題に関係ないです. setqってグローバルですものね(^^;; っということで, じつは, elispにはトッ プレベルでローカル変数を定義できないから, 逆に問題がないんですね. smalltalkも同じようなもんですね. >そもそも「そういうのが実現できると嬉しい」というのは分かるん >ですけど,「そういうのが実現できないといけない」ではない以上 >変更に慎重になるのは当然だと思います. そうですね. 実現できないといけないといってもいろいろなレベルがあるでしょ うけどね. 言語機能的になくちゃいけないのか? あることを実現するのになく ちゃいけないのか? と. 今回は後者だと思っていたのですが... # 十分, 代わりになる機能に気づいてしまいました(^^;;; >スコープの定義が不明確ですが,私の主張の根幹は「バインディン >グを合成しても構わないのか」というものです.また,「合成して >も構わないとしてその状態はどのように指定されるべきか」が明確 >でないと採用できないと思ってます. 今回他の方法が見つかったので, このリクエストは取り下げます. でも, この話しはMFLの話しとしても面白いと思うので, 何か考えがまとまっ たら, またお騒がせするかも知れません. その時はよろしくお願いします (__;;; で, 方法というのは, new_binding = proc{binding}.call を使う方法なんです. procないで定義された変数はそこだけで有効ですから, これを使えば, 目的は果たせることに気づきました. # self(main)は共有しちゃうんですが, それはそれでまあいいかなと... いろ # いろと問題がないではないんですが... 実は, この方法は昔から気づいていたんですが, ある現象(バグ?)のために勘 違いしていたのでした. それが何かというと, これです: irb:002:0> p = proc{binding}.call # irb:003:0> eval "foo = 1", p 1 irb:004:0> foo 1 ローカル変数が共有されていますよね? おかしいなと思いつつ, そういうもん だと信じていたのでした. でも, irb:006:0> q = proc{dummy = 1; binding}.call # irb:007:0> eval "bar = 1", q 1 irb:008:0> bar NameError: undefined local variable or method `bar' for # irb:8 と, proc内で変数を定義すると変数の空間が分離するらしい(そういう実装な んですね?)ことに気づきました. 実装上は, どうなっていようとも, proc内はローカル変数の空間は独立(いや 継承する)となっていますので, bindingのバグだと思うのですが? ついでに, リクエストしちゃいますが, Cにはブロックがありますよね? { int foo = 1; { int foo = 2; ... みたいなものです, これって良く使うでしょ? rubyでも proc { ... }.call とすればできるんですけど, 何か間抜けでしょ? そういうわけで, rubyにもあっ ても良いと思うのですが? block do ... end 結構意味がはっきりしているので, 構文として採用しても良いと思います. block ... end いかがでしょう? でも, begin ... end と間際らしいかな... もっとlocalな ことを明示的に表すように. local ... end let ... end progn ... end とか? いかがでしょう? >|うーん. それなりの機能を持ったスコープを作る構文orイテレータでも良いん >|ですけどね... > >その場合には「それなりの機能」を定義して下さいよお. ># 『言うだけは簡単』は勘弁して欲しい. 上記にリクエストを出しました(^^;;; >あと,実装の話をするとローカル変数はコンパイル時に計算される >部分が多いので動的に変更するのはすっごく大変です.evalのよう >なコンパイル前に指定するのは不可能ではないでしょうが,イテレー >タブロックの範囲内だけスコープを変更するなどと言うのはほとん >ど不可能でしょう.パーザを再実装するくらい大変です. これは, 完全に独立なlocal変数ということですね? 実はイテレータブロック のスコープそのままで良かったみたいです(__;;; >構文は…いまさら構文を追加するのは避けたい…. 上記のようなものならあっても良いとは思いますが... >メソッド一個定義して終り,くらいだと簡単にコストが計算できる >んですけど,今回のような変更の場合は先が読めないのです.ご理 >解下さい. いろいろと御迷惑をおかけしました(__;; >うーん,やっぱり無理して独立したバインディングを用意しようと >してるからではないかという気がして来ました.なんか場当たり的 >な対応をするのではなく, だからこそ, 欲しかったんですけど(^^;;; >もっと根本から考え直した方が良いような気がします. >|privateとして定義する何かうまい手がありますかね? > >あ,そうそう.scopeにはこれから定義するメソッドがprivateかど >うかっていう情報も入ってるんでした.うーむ. procのbindingは問題ありませんでした: irb:013:0> eval "def foo;end", q nil irb:014:0> private_methods [... "foo" ...] >たとえば同じ環境に見えて独立してるってのをすっぱり諦めて,モ >ジュール(あるいはクラス)単位で別のスコープを見せるってのは? >言語のモデルとあまり離れていないので,実装はずっと楽だと思い >ますよ.private/publicの辺りで修正は必要になりそうだけど. いや. こっちはこっちでやろうと思っていました. それこそオブジェクト空間 のcdに相当するものですね(^^;;; # ローカル変数を共有できないのがちょっとというかかなり違いますけどね. この機能とshell.rbをつかってshellモードを作ろうかなと... そうすると, sh = Shell.cd("/tmp") for dir in ["dir1", "dir3", "dir5"] sh.mkdir dir sh.pushd(dir) do sh.echo("TEST") > "tmpFile" end end は irb> shell shell> cd "/tmp" shell> for dir in ["dir1", "dir3", "dir5"] shell> mkdir dir shell> pushd(dir) do shell> echo("TEST") > "tmpFile" shell> end shell> end 見たくできます. ほんとのshellっぽいでしょ? __ ................................石塚 圭樹@日本ラショナルソフトェア... ----------------------------------->> e-mail: keiju@rational.com <<---