Ruby: экспортировать переменную в локальное пространство имен - PullRequest
2 голосов
/ 11 августа 2011

Я хочу программно вставить новую переменную в локальное пространство имен Ruby.Например, я хочу, чтобы я мог написать

label = 'some_name'
# some code equivalent to
#   some_name = 3
# but using only 'label' to get the name.
puts some_name  # returns 3

Что я должен поставить посередине, чтобы это сделать?

Ответы [ 3 ]

3 голосов
/ 11 августа 2011

Я ответил на другой вопрос SO , похожий на этот .Краткий ответ таков: если вы специально хотите создать локальную переменную с именем, основанным на значении другой переменной, то сделать это невозможно.Если вы просто хотите, чтобы выглядело так, как будто вы создали локальный объект, но это действительно магия рубина, то ответ типа @ mikong - один из способов.

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

label = 'some_name'
self.instance_variable_set("#{label}", 3)
puts @some_name

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

2 голосов
/ 11 августа 2011

Следующее не совсем код между двумя линиями, которые вы упомянули выше:

class Example
  attr_accessor :label

  def method_missing(name, *args, &block)
    return some_processing  if name == label.to_sym
  end

  def some_processing
    3 # of course, this can be something more complicated
  end

  def test
    @label = 'some_name'
    puts some_name
  end

end

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

Лично я думаю, что ваши требования кажутся немного опасными в том смысле, что имя "переменной" меняется. Я бы, вероятно, не использовал код в моем примере. Я думаю, в зависимости от требований проекта, я подумаю о другом подходе.

2 голосов
/ 11 августа 2011
label = 'some_name'
eval "#{label} = 3"
puts eval "#{label}"
puts local_variables

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

puts some_name

... потому что, если бы вы знали, какие локальные переменные вы собираетесь создать, не было бы необходимости называть их с помощью кода времени выполнения. И это хорошо, потому что интерпретатор не сможет puts some_name напрямую, потому что он никогда не анализировал назначение для some_name. Но это там и локально , как показывает puts local_variables.

...