9

言葉の悪い質問のタイトルについてお詫びします-それをより良くする方法がわかりません!

次のコードで、を実行するときにruby bar.rb、どうすれば出力するbar.rbのではなく、出力させることができfoo.rbますか?

foo.rb

module Foo
  def filename
    __FILE__
  end
end

bar.rb

require_relative 'foo'
include Foo

puts filename # outputs 'foo.rb'

これは、コードが実行されるたびに、そのコードの場所(およびgit ref)を記録するライブラリ関数用です。

4

2 に答える 2

4

__FILE__あなたの質問は、Rubyインタープリターソースをクラックして開き、実際にどのように機能するかを確認するように私を刺激しました。答えは非常に興味深いものです。パーサー内に実装されています。レクサーには、の特別なトークンタイプがあり__FILE__ます。パーサーはそのトークンを検出すると、それを文字列定数に変換します。この文字列定数には、パーサーが作業しているファイルの名前が含まれています。

ext / ripper / ripper.cの14948行目から:

case keyword__FILE__:
return NEW_STR(rb_external_str_new_with_enc(ruby_sourcefile, strlen(ruby_sourcefile),
                        rb_filesystem_encoding()));

これにより、Rubyインタプリタソースをハックするか、Rubyソースをインタプリタに渡す前に別__FILE__のプリプロセッサに変換する独自のプリプロセッサを作成しない限り、インクルードファイルの名前を返すことは完全に不可能であることが明確になるはずです。__FILE__

于 2012-10-15T15:05:28.760 に答える
1

あなたが使うことができるかもしれないトリックがあります。ブロックをメソッドに渡す場合は、ブロッククロージャーを使用してそのソースを判別できます。何かのようなもの:

def filename(&blk)
  blk.eval "__FILE__"
end

しかし、繰り返しになりますが、それはあなたがブロックを通過しなければならないことを意味します。

正直なところ、私はあなたが何を達成しようとしているのだろうか、b / cはいくつかの一般的なコア拡張メソッドを作成する以外に、これはおそらくあなたが本当にやりたくないことです。

于 2012-10-21T12:36:26.143 に答える