2017-01-14 12 views
1

Dir.foreachループ内の変数のスコープがローカルなのはなぜですか?Dir.foreach()のローカルスコープRuby

私はファイルから必要な情報を見つけて変数と同じに設定するまでファイルをループしていましたが、ループの外側では変数を見ることができませんでした。私は今、グローバル変数を使用していますが、それはRubyで好まれないので、私はそれをする必要はありません。

答えて

1

ブロック内に変数を設定した場合、以前に定義された変数が外側スコープにない限り、外側スコープからは使用できません。

「グローバル」とは最も外側のスコープを意味します。スコープの主な2つのレベル、メソッドとブロックがあります。いずれの場合も、同じ動作が表示されます。

a = 0 
def foo 
    a = 1 
    b = 2 
end 
foo 
a # => 1 
b # => NameError 

1.times do 
    a = 2 
    b = 3 
end 
a # => 2 
b # => NameError 
+0

ありがとうございます。私はそれまでにそれに遭遇したことがないことに驚いています。それが教訓であることを願っています。私は非常に頻繁にブロックをこのように使用しないか、他の何らかの理由で変数を宣言していると思います。今、私のグローバル変数はなくなりました。 – Greg

0

あなただけの一つの要素は、そうでなければ、あなたはそれだけではなく、外にそのブロックのスコープで定義されたブロック内の変数を定義する際にMaxpleは、言っfind

fname = Dir.foreach('.').find { |each| each =~ /store/i } 

を使用する必要がある場合。変数を内側と外側の両方で使用する場合は、ブロックの前に変数を定義する必要があります。

しかし、前述のように、ほとんどの場合、代わりにEnumerableモジュールの関数を使用できます。有用なものはselectfindmapany?です。

0

ローカル変数は、定義されているスコープに対してローカルなので、結局、ローカル変数と呼ばれています。

Rubyには、スクリプト、モジュール/クラス定義、メソッド、ブロック/λリテラルの4つのローカル変数スコープがあります。これらの4つのうち、ブロックスコープのみが入れ子になり、ブロックのみがクロージャーになります。

したがって、ブロック内にローカル変数を定義すると、ローカル変数はそのブロックにローカルになります。しかし、ローカル変数をブロックの外側に定義すると、ブロックスコープが外側のスコープの内側にネストされるため、(ブロックローカル変数として明示的に宣言されている場合を除いて)ブロックで使用できるようになります。ブロックスコープは周囲のレキシカル環境で閉じるため、外部スコープが終了した後でブロック内で使用できるようになります。

注:たとえfor/inイテレータはこの特別場合には、ブロックは独自のスコープを取得していない、ブロックでeachにメッセージにdesugar。回避するもう一つの理由for/in

foo = :outerfoo 
bar = :outerbar 

[nil].each do |*; bar| 
    foo = :innerfoo 
    bar = :innerbar 
    baz = :innerbaz 
end 

foo #=> :innerfoo 
bar #=> :outerbar 
baz # NameError: undefined local variable or method `baz' for main:Object 

for * in [nil] 
    looks_local_but_isnt = :huh 
end 

looks_local_but_isnt #=> :huh 
関連する問題