Отменить определение переменной в Ruby
-
18-09-2019 - |
Вопрос
Допустим, я использую irb
, и введите a = 5
.Как удалить определение a
так что набираю a
возвращает NameError
?
Некоторый контекст:позже я хочу сделать это:
context = Proc.new{}.binding
context.eval 'a = 5'
context.eval 'undef a' # though this doesn't work.
Решение
Есть удалить_класс_переменную, Remove_instance_variable и Remove_const методы, но в настоящее время нет эквивалента для локальных переменных.
Другие советы
Вы можете избежать отмены объявления переменной, уменьшив область, в которой она существует:
def scope
yield
end
scope do
b = 1234
end
b # undefined local variable or method `b' for main:Object
Вы всегда можете «очистить» реестр irb от локальных переменных, вызвав подоболочку irb.Подумайте о том, как оболочки Bash работают с неэкспортированными переменными среды.Поскольку вы упомянули интерактивный режим, это решение должно подойти для этого.
Что касается производственного кода, я бы не хотел отменять определение локальных переменных как часть решения — хэши с ключами, вероятно, лучше подходят для такого типа сценария.
Вот что я имею в виду:
$ irb
irb(main):001:0> a = "a"
=> "a"
irb(main):002:0> defined? a
=> "local-variable"
irb(main):003:0> irb # step into subshell with its own locals
irb#1(main):001:0> defined? a
=> nil
irb#1(main):002:0> a
NameError: undefined local variable or method `a' for main:Object
from /Users/dean/.irbrc:108:in `method_missing'
from (irb#1):2
irb#1(main):003:0> exit
=> #<IRB::Irb: @context=#<IRB::Context:0x1011b48b8>, @signal_status=:IN_EVAL, @scanner=#<RubyLex:0x1011b3df0>>
irb(main):004:0> a # now we're back and a exists again
=> "a"
В настоящее время у вас нет возможности удалить глобальные переменные, локальные переменные и переменные класса.Однако вы можете удалить константы, используя метод «remove_const».
По духу вопроса вы можете ограничить переменную областью действия, предполагая, что вас устраивает, что другие локальные переменные привязаны к той же области.Это особенно полезно, если вы определяете что-то в классе и не хотите, чтобы локальная переменная оставалась в объявлении класса.
Единственный способ, которым я могу это сделать, - это Integer#times
или Array#each
вот так:
1.times do |a|
a = 5
# code…
end
[5].each do |a|
# code…
end
Помимо этого, вероятно, существуют другие, даже более чистые способы ограничения блоком.Они не так чисты, как мне хотелось бы, и мне бы хотелось посмотреть, есть ли у кого-нибудь более чистый метод, который можно использовать для этого.