在Ruby中,顶级作业有什么作用?

问题描述 投票:0回答:4

我在.rb文件的顶层有以下代码:

class Times
    def initialize(n)
        @n = n               
    end
    def each()        
        (1..@n).each {yield}
    end
end
three_times = Times.new(3)

def f()
    Times.new(3).each {puts 'Test'}
end
f()

这可以工作,并按预期打印“测试”三次。但是,如果我用Times.new(3)替换f中的three_times,即three_times.each {puts 'Test'},我收到一个错误:

`f': undefined local variable or method `three_times' for main:Object (NameError)

为什么这不起作用?为什么Times可以从f内部访问,但不能访问three_times

更一般地说,顶层的任务究竟是什么(例如three_times = Times.new(3))呢?

ruby global-variables variable-assignment toplevel
4个回答
2
投票

为什么这不起作用?为什么Times可以从f内部访问,但不能访问three_times

名称以小写字母开头的变量是局部变量。局部变量是它们定义的范围的局部变量(这就是它们被称为局部变量的原因。)

名称以大写字母开头的变量是常量。常量首先在默认的常量范围中查找,然后在词法上向外查找,然后通过继承动态向上查找。

更一般地说,顶层的任务究竟是什么(例如three_times = Times.new(3))呢?

没什么特别的。它在其他任何地方做的任务都是一样的。在这种情况下,它:

  1. 取消引用变量(常量)Times,让我们称这个对象为o1。
  2. 计算文字整数表达式3,让我们调用结果对象o2。
  3. 将消息new发送到o1,将o2作为参数传递。让我们来回复一下该消息发送o3。
  4. 将o3绑定到名为three_times的局部变量。

正如您所看到的,那里没有任何特定于脚本范围或顶级的特定内容。


1
投票

这是因为它正在寻找一个名为“three_times”的局部变量。如果您希望将“three_times”设置为“top-level”或“global”,请在变量名前加上$,使其为“$ three_times”。


1
投票

因为

  • three_times是一个局部变量
  • 局部变量只能在特定范围内访问
  • 红宝石中的def创造了一个新的范围

因此,当调用f时,它看不到或无法访问three_times

要访问three_times,请将其更改为全局变量$three_times或实例变量@three_times

你能够引用类Times的原因是它是一个常量,ruby经历了一个单独的常量查找过程。


def的散步问题

您还可以使用块来定义方法来访问局部变量,该方法可以避开整个范围门问题。我有时在编写rake任务时这样做但很少在脚本之外执行。

three_times = Times.new(3)
define_method :foo do
  three_times.each { puts 'Tests'}
end
foo

0
投票

您的代码适合我,没有错误。你可以sucecsfully打电话给f()

© www.soinside.com 2019 - 2024. All rights reserved.