Неопределенная переменная в Ruby - PullRequest
45 голосов
/ 06 января 2010

Допустим, я использую irb и набираю a = 5. Как удалить определение a, чтобы при наборе a получалось NameError?

Некоторый контекст: позже я хочу сделать это:

context = Proc.new{}.binding
context.eval 'a = 5'
context.eval 'undef a'  # though this doesn't work.

Ответы [ 5 ]

46 голосов
/ 06 января 2010

Существует remove_class_variable , remove_instance_variable и remove_const , но в настоящее время нет эквивалента для локальных переменных.

22 голосов
/ 14 декабря 2014

Вы можете избежать отмены объявления переменной, уменьшив область, в которой существует переменная:

def scope 
  yield
end

scope do 
  b = 1234
end

b  # undefined local variable or method `b' for main:Object
13 голосов
/ 08 июля 2010

Вы всегда можете «очистить» реестр локальных переменных 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"
0 голосов
/ 31 декабря 2018

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

Единственный способ, которым я могу думать, это сделать с помощью Integer#times или Array#each, например:

1.times do |a|
  a = 5
  # code…
end

[5].each do |a|
  # code…
end

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

0 голосов
/ 06 января 2010

В настоящее время у вас нет возможности удалять глобальные переменные, локальные переменные и переменные класса. Вы можете удалить константы, используя метод "remove_const", хотя

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...