2013-07-24 2 views
8

Я пытаюсь динамически создавать локальные переменные в Ruby с использованием eval и мутировать массив локальных переменных. Я делаю это в IRB.Как мне динамически создать локальную переменную в Ruby?

eval "t = 2" 
local_variables # => [:_] 
eval "t" 
# => NameError: undefined local variable or method `t' for main:Object 
local_variables << "t".to_sym # => [:_, :t] 
t 
# => NameError: undefined local variable or method `t' for main:Object 
+2

Почему вы пытаетесь это сделать? В чем цель? –

+0

@ Серхио Туленцев я задал себе тот же вопрос. Скорее всего, исходная проблема может быть решена гораздо проще. –

ответ

9

Вы должны использовать правильный binding. В IRB, например, это сработало бы:

irb(main):001:0> eval "t=2", IRB.conf[:MAIN_CONTEXT].workspace.binding 
=> 2 
irb(main):002:0> local_variables 
=> [:t, :_] 
irb(main):003:0> eval "t" 
=> 2 
irb(main):004:0> t 
=> 2 
+5

Как насчет IRB? 'ruby myfile.rb'? –

+0

Правильный ответ! Спасибо. – ppone

+0

@SergioTulentsev Я не уверен, что 'TOPLEVEL_BINDING' и другие экземпляры привязки в ObjectSpace, похоже, не работают. – Stefan

15

Вам необходимо синхронизировать оценки с одним и тем же объектом привязки. В противном случае одна оценка имеет свою собственную область.

b = binding 
eval("t = 2", b) 
eval("local_variables", b) #=> [:t, :b, :_] 
eval("t", b) # => 2 
b.eval('t') # => 2 
+0

Спасибо, + 1'd :) –

+0

Спасибо. Как получить привязку для основного объекта. Каждый раз, когда вы запускаете b = binding; он возвращает другой объект привязки. – ppone

+0

Просто сделайте это один раз. – sawa

9

Вы можете установить переменные экземпляра, как это:

instance_variable_set(:@a, 2) 
@a 
#=> 2 
+7

Вопрос не в переменных экземпляра. –

+1

Это правда, но, возможно, это может также решить проблему, которую имеет ОП. Как уже было сказано в моем комментарии к первому вопросу, я ожидаю, что для исходной проблемы будет намного проще решение. –

+0

также как альтернативный метод не забывайте о 'define_method'. – lakesare

Смежные вопросы