我写了这个迷你测试程序来保存数组中的数组:
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>'
我错了什么?感谢
答案 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