From: Koji Arai Date: 1998-11-21T06:33:04+09:00 Subject: [ruby-list:10996] Re: スコープの範囲 新井です。 ちょっと引用が多くて長くなってしまいましたが御勘弁 を。 >>> From: matz@netlab.co.jp (Yukihiro Matsumoto) >>> Date: Fri, 20 Nov 1998 11:38:47 +0900 >>> Subject: [ruby-list:10983] Re: スコープの範囲 > Rubyのローカル変数の有効範囲は静的に決まります 「静的」の意味がよくわからなかったのですが、コンパ イル時にスコープを決めているということでしょうか? で、結局は 「定義より前の"行"で、ローカル変数が有効になることはない」 ということになる? #!/usr/local/bin/ruby eval %q{ $a = "a" def b; "b" end c = "c" } begin p $a p b p c rescue NameError p "undefined" end __END__ "a" "b" "undefined" これは、evalが独自のスコープを持っているからではな く、コンパイルが別に行われているからと解釈すればよ いのかな? まぁ、結局は 「evalは、イテレータと同じようにローカル変数のスコープを持つ」 ということになる? "イテレータと同じように"というのは重要(後述) >>> From: Shin-ichro Hara >>> Date: Fri, 20 Nov 1998 12:28:14 +0900 >>> Subject: [ruby-list:10990] Re: スコープの範囲 > 原です。 > > ローカル変数のスコープで注意すべきことについて、くどくど > 書いたのが [ruby-list:1212] にあります。よろしかった御覧 > 下さい。 > 拝見させて頂きました。ありがとうございます。 以下、サンプルスクリプト以外を引用させて頂きました。 >>> From: sinara@blade.nagaokaut.ac.jp >>> Date: Mon, 9 Dec 96 16:40:56 JST >>> Subject: [ruby-list:1212] Summary (Re: [Q] Scope of local variable) > 原です。 > > << 局所変数について >> > > 【1】ローカル変数のバインドは静的に行われ、ローカル変数は最初の代 > 入文で定義される。 > > この場合、静的とは、実行前にスクリプトのコード上で、という感じの > 意味。 > 「静的に」という用語が… 再掲、 「*いかなる場合でも*定義より前の"行"で、ローカル変 数が有効になることはない」 あってます? 「ローカル変数のスコープは定義からブロック(?)の終りまで」 の方がいいかなぁ。 > 【2】イテレータのブロックでは、そこで初めて定義されたローカル変数は > 局所化される。 > イテレータではブロック外部のローカル変数(小文字で始まるの変数)にアク > セス出来る。 局所化されるかどうかを文法で区別できないのは少し痛 いですね。 イテレータを書くときは、常に局所変数の名前がダブら ないように気を使わなくてはいけないですから。 evalも同じ。 #!/usr/local/bin/ruby $assign = %Q{v = "2"; p v} eval $assign # => 1 局所化されてる v if defined(?v) # => v = 1 # eval より前に定義 p v # => 1 eval $assign # => 2 局所化されない p v # => 2 eval によって値が壊される __END__ でも、いまさら my(perl)やglobal(tcl)は導入したくないなぁ。 > メソッドの定義では外部のローカル変数(小文字で始まるの変数)にアクセス > できない。 これは、自然に受け入れられる > > 【3】定義は、代入を実行することによってなされるのではなく、実行以前に > スクリプト中に代入文が現れたときになされる、 > そうだったのか〜。「静的」だからかぁ。 > 【4】定義とは、いわばアクセス権を与えることである。defined?(j) は、 > j という名前の変数へのアクセス権の有無を判定する。その場でアクセ > ス権がない名前の変数でも、存在していないわけではない。 これもずいぶん特殊ですね。 > > イテレータブロック内のローカル変数は、各回ごとに消滅する。 > > > 他にも気をつけることあるかな。 > [ruby-list:10854]の >>> From: matz@netlab.co.jp (Yukihiro Matsumoto) >>> Date: Mon, 16 Nov 1998 11:27:10 +0900 >>> Subject: [ruby-list:10854] Re: IO#pos= > いやあ,一般にselfは省略可能なんですが,属性代入に関してはロー > カル変数の代入と全く区別がつかないので,省略できません.とい は、重要ですね。私は、これを読むまで xx= メソッド は作るまいと心に誓ってました。 class Test attr "v", TRUE def v1(arg) self.v = arg # v= メソッド呼び出し p @v end def v2(arg) v = arg # v= メソッドではなく、局所変数への代入 p @v end end test = Test.new test.v1(true) #=> true test.v2(false) #=> true 以上、うーん、さらに複雑にしてしまったなぁ。実際の ところは、局所変数で困ることはほとんどないんですけ どね。 おまけ save, $/ = $/, nil $_ = gets $/ = save こういう書き方は、なんか嫌です。$/ は、gets(nil)で 代用できるからいいんですけど。 というわけで、以下みたいなのを考えて見ました。 #!/usr/local/bin/ruby # # perl の local() を実現する (ただし、$global変数だけ) # (こういうのを「深い束縛(deep binding)」と言うらしい) # module LocalScope def local(global_vars) save = eval("[" + global_vars + "]") yield eval(global_vars + ",*dummy = save") end end include LocalScope $/, $; = "1", "2" local("$/, $;") { $/, $; = "3", "4" local("$/, $;") { $/, $; = "5", "6" p $;, $/ } p $;, $/ } p $;, $/ __END__ "6" "5" "4" "3" "2" "1" ほら、perlみたいになった。(汚さが ^^;) # :symbol が使えればと思ったのですが、:$/ から$/の値 # を取り出す方法がわからなかったんです。