【问题标题】:Ruby local variable is undefinedRuby 局部变量未定义
【发布时间】:2012-03-29 02:23:49
【问题描述】:

我有以下 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 访问同一文件。

我的理解有什么问题?

【问题讨论】:

  • 您说“我一直认为无法从 [...] 函数外部访问局部变量”。那么,为什么你会惊讶于你的局部变量只在 puts 行的函数内部呢?
  • 因为其他编程语言不同
  • 试试@local_var = "你好"

标签: ruby local-variables


【解决方案1】:

在 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 进入,因此您无法在 hello 方法中访问您的 local_var


您可以使用 Scope Flattening 概念将变量通过这些门。

例如,您可以使用Module#define_method,而不是使用def 来定义您的方法。

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

示例取自Metaprogramming Ruby

【讨论】:

    【解决方案2】:

    local_var 是一个局部变量。局部变量在它们定义的范围内是局部的。(这就是为什么它们被称为“局部变量”,毕竟!)所以,显然,因为local_var 是在脚本范围内定义的,所以你无法在方法范围内访问它。

    【讨论】:

    • 如果我在车里,口袋里有零钱,那么车里就有零钱。许多其他语言将局部变量转发到内部范围,因此没有理由将 Ruby 的行为视为不言而喻。
    • @AdamTolley 你是完全正确的,但我猜 Ruby 可能是 Jorg 的第一语言,而且范围对他来说似乎很明显!
    • @AlexanderSuraphel:实际上,这大约是我的第十五种语言,尽管当我写下这个答案时,我可能又多了十几种。我真的不跟踪。
    猜你喜欢
    • 2013-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多