Локальная переменная Ruby не определена - PullRequest
35 голосов
/ 12 марта 2012

У меня есть следующий код Ruby:

local_var = "Hello"

def hello
  puts local_var
end

hello

Я получаю следующую ошибку:

local_variables.rb:4:in 'hello': undefined local variable or method 'local_var' 
for main:Object (NameError) from local_variables.rb:7:in '<main>'

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

Но теперь я определил локальную переменную в файле и пытаюсь получить доступ из функции INSIDE к тому же файлу.

Что не так с моим пониманием?

Ответы [ 2 ]

52 голосов
/ 12 марта 2012

В Ruby локальные переменные доступны только в той области, в которой они определены.Всякий раз, когда вы входите / выходите из Класса, Модуля или Метода, определяющих вашу область, изменяется в Ruby.

Например:

v1 = 1

class MyClass # SCOPE GATE: entering class
  v2 = 2
  local_variables # => ["v2"]

  def my_method # SCOPE GATE: entering def
    v3 = 3
    local_variables  # => ["v3"]
  end # SCOPE GATE: leaving def

  local_variables # => ["v2"]
end # SCOPE GATE: leaving class

Эти точки входа и выхода называются Вратами Области.Поскольку вы входите через Scope Gate через определение метода, вы не можете получить доступ к своему local_var внутри hello методу.


Вы можете использовать концепцию выравнивания области для передачи вашей переменной через эти ворота.

Например, вместо использования def для определения вашего метода вы можете использовать Module#define_method.

local_var = "Hello"

define_method :hello do
  puts local_var
end

Таким же образом вы можете определять свои классы с помощью Class#New, чтобы ваша область действия не изменялась привы проходите через определение класса.

local_var = 'test'

MyClass = Class.new do
  puts local_var #valid
end

вместо

class MyClass
  puts local_var #invalid
end

Таким же образом вы должны использовать Module#New, если вы хотите передать свои локальные переменные через ворота модуля.

Пример взят из Метапрограммирование Ruby

0 голосов
/ 13 марта 2012

local_var является локальной переменной. Локальные переменные являются локальными для области, в которой они определены. (Именно поэтому они называются «локальными переменными», в конце концов!) Так что, очевидно, поскольку local_var определено в области действия сценария, вы не можете получить доступ к нему в области действия метода.

...