0

私はシンボルについて学んでいますが、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?) は、コード行の「実行」を開始する前に、ファイル全体を一度解析しているようですが、まだクラスを構築していません。おそらくそれはある種の「プレパス」ですか?

4

2 に答える 2

1

ファイルは行ごとに解釈されます。まだ定義されていないコードで何かを参照することはできません。読み取られることは、初期化されることと同じではありません。

Ruby 1.9.2は以下を出力しますが、これはもう少しわかりやすいかもしれません。

foo2.rb:7:in `<main>': uninitialized constant Object::DefinedAtEnd (NameError)
于 2012-06-01T18:34:57.323 に答える
1

ソース ファイルの解析とそのコードの実行には違いがあります。それは2段階で起こります。解析中、オブジェクトの名前 (理論的に割り当てられる可能性のあるクラス名とすべての変数を含む) は、シンボル テーブルに保持されます。とはいえ、これはおそらく信頼すべきではない実装の詳細です (実際には何も役に立たないため、なおさらです)。

一般に、シンボルはインターンされた文字列です。つまり、ガベージ コレクションされることはなく、インタープリター全体で 1 回だけ存在する文字列です。

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

文字列とは異なり、シンボルもその場で変更できず、不変です。

于 2012-06-01T20:42:16.753 に答える