undefined局部变量或方法`arr'

时间:2013-12-14 09:39:44

标签: ruby-on-rails ruby

我写了这个迷你测试程序来保存数组中的数组:

arr = Array.new

def w(num,text)
  arr << [num, text]
end

w(0123, "was")
w(3453, "hallo")
w(0123, "umbau")
w(0342, "farruko")

arr.each do |f|
 puts f.first.to_s + f.last
end

但不知怎的,我得到了错误:

arraytest.rb:5:in `w': undefined local variable or method `arr' for main:Object
(NameError)
        from arraytest.rb:8:in `<main>'

我错了什么?感谢

4 个答案:

答案 0 :(得分:2)

您将arr定义为变量

arr = Array.new

但该变量在w方法的范围内不可见。第一次调用该方法时,会出现错误。

w(0123, "was")

如果要编辑arr,则需要将其作为参数传递给函数。

def w(arr, num, text)
  arr << [num, text]
end

可以使用动态定义方法解决问题,例如define_method传递lambda,例如

define_method(:w)do | num,text |       arr&lt;&lt; [num,text]     端

lambda可以访问周围的环境,但在大多数情况下,这是一个问题,而不是一个优势。 lambda将防止垃圾收集,你最终可能很难调试内存泄漏。

This talk from Aaron Patterson有一些非常有趣(高级)的细节。

底线:如果您需要定义一个简单方法,请将值作为参数传递。不要使用花哨的元编程,特别是如果你是Ruby的新手并且你不知道它的区别。

答案 1 :(得分:1)

如果要在方法arr中访问顶级本地变量#w,请按如下所示编写代码。

arr = Array.new

define_method(:w) do |num,text|
  arr << [num, text]
end

w(0123, "was")
w(3453, "hallo")
w(0123, "umbau")
w(0342, "farruko")

arr.each do |f|
 puts f.first.to_s + f.last
end
# >> 83was
# >> 3453hallo
# >> 83umbau
# >> 226farruko

def创建一个新范围,因此您在方法arr中看到的局部变量w仅限于该方法。顶级局部变量arr与方法w内的变量不同。现在,如果要使用外部局部变量arr,请使用支持块的Module#define_method。在Ruby中,块是封闭的,因此您可以访问周围环境。

答案 2 :(得分:1)

arr不在您定义的方法范围内。

您可以通过将其初始化为方法范围内的变量,或将其存储为@arr - 实例变量来解决此问题。哪种方法更好取决于使用方案。

请注意,如果您使用的是实例变量,则可以在方法中懒惰地初始化,如下所示:

def w(num, text)
  (@arr ||= []) << [num, text]
end

答案 3 :(得分:0)

奥雅纳的答案几乎是正确的,但他错过了一个重要的细节。

Module#define_method是一种private实例方法,当前对象可以调用 (此处为main })。

因此,该代码最终会产生错误:

 undefined method `define_method' for main:Object

通过Object#send

调度方法解决此问题
arr = Array.new

Kernel.send(:define_method, :w) do |num,text|
  arr << [num, text]
end

w(0123, "was")
w(3453, "hallo")
w(0123, "umbau")
w(0342, "farruko")

arr.each do |f|
 puts f.first.to_s + f.last
end
# >> 83was
# >> 3453hallo
# >> 83umbau
# >> 226farruko