2017-01-14 6 views
1

Почему область переменных в цикле Dir.foreach локальная?Локальная область в Dir.foreach() Ruby

Я зацикливал файлы, пока не нашел информацию, которая мне нужна из файла, и установите ее равной переменной, но вне цикла переменная не видна. На данный момент я использую глобальную переменную, но, поскольку это не одобрено в Ruby, я бы не хотел этого делать.

ответ

1

, когда вы устанавливаете переменную в блоке, если в внешней области не существует ранее определенной переменной, она не будет доступна из внешней области.

«глобальный» означает только внешний вид. Существует два основных уровня охвата - метод и блок. В любом случае вы увидите такое же поведение.

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

Если вам просто нужно один элемент использовать find

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

В противном случае, что сказал Maxple, когда вы определяете переменную внутри блока, когда он определен в рамках этого блока только, но не снаружи. Вы должны определить переменную перед блоком, если хотите использовать его как внутри, так и снаружи.

Но, как уже упоминалось, вы почти всегда можете использовать функцию на модуле Enumerable. Полезными являются select и find и map и any?, лучше всего ознакомиться с документацией.

0

Локальные переменные являются локальными для области, в которой они определены. Вот почему они все-таки называются «локальными» переменными.

В Ruby имеется четыре области локальных переменных: сценарий, определение модуля/класса, метод и блок/λ-литерал. Из этих четырех гнезд только блочные области, и только блоки могут быть замыканиями.

Итак, если вы определяете локальную переменную в блоке, она локальна для этого блока. Если, однако, вы определяете локальную переменную вне блока, то она будет доступна в блоке (если явно не объявлено как локальная переменная блока), поскольку область блока гнездится внутри внешней области. Он будет даже доступен в блоке после окончания внешнего диапазона, потому что области блоков закрываются вокруг их окружающей лексической среды.

Примечание: даже если for/in итераторы desugar в сообщение для each с блоком, в этом специальном случае блок не получает свою область применения. Еще одна причина избежать 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