Ruby类名称在符号列表中,但解释器无法识别

时间:2012-06-01 18:31:42

标签: ruby interpreter symbols

我正在学习符号,当我将其作为文件的第一行转储时,我惊讶地发现文件中的所有符号都包含在Symbol.all_symbols数组中。 但是,如果我尝试访问进一步定义的类,我会得到NameError,换句话说,它是一个无法识别的符号。

puts "DefinedAtEnd is in symbol list: \
 #{Symbol.all_symbols.select {|s| s =~ /^DefinedAtEnd/} != nil} "
puts "do_it is in symbol list: \
 #{Symbol.all_symbols.select {|s| s =~ /^do_it/} != nil} "
puts "foo is in symbol list: #{Symbol.all_symbols.select {|s| s =~ /^foo/} != nil} "

#d = DefinedAtEnd.new    # This will get a NameError

class DefinedAtEnd
  def do_it
    foo = 'bar'
    puts 'In method do_it'
  end
end

运行以上结果会得到以下结果:

DefinedAtEnd is in symbol list: true 
do_it is in symbol list: true 
foo is in symbol list: true 

但如果我取消注释行d = DefinedAtEnd.new,则会收到以下错误:

uninitialized constant DefinedAtEnd (NameError)

似乎解析器(metparser?)在开始“执行”代码行之前解析整个文件一次,但它还没有构建类。也许这是某种“预先通过”?

2 个答案:

答案 0 :(得分:1)

逐行解释文件;你不能在代码中引用尚未定义的 - 被读取与初始化不同。

Ruby 1.9.2输出以下内容,这可能会更有启发性:

foo2.rb:7:in `<main>': uninitialized constant Object::DefinedAtEnd (NameError)

答案 1 :(得分:1)

解析源文件和执行代码之间存在差异。它分两个阶段发生。在解析期间,对象的名称(包括类名和理论上可能被分配的所有变量)被固定到符号表中。也就是说,这是一个你可能不应该依赖的实现细节(更是如此,因为你无法用它做任何有用的事情)。

通常,符号是实习字符串,即从不被垃圾收集的字符串,在整个解释器中只存在一次。

"foo".object_id == "foo".object_id   # => false
:foo.object_id == :foo.object_id     # => true

与字符串不同,符号也不能在适当的位置更改,它们是不可变的。