对措辞不佳的问题标题道歉 - 不知道如何把它变得更好!
在以下代码中,当我执行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)。
答案 0 :(得分:4)
你的问题刺激我破解Ruby解释器源并看看__FILE__
实际上是如何工作的。答案非常有趣:它在解析器中实现。词法分析器具有__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()));
我认为这应该清楚地表明,尝试使__FILE__
返回包含文件的名称是完全不可能的,除非您破解Ruby解释器源,或者编写自己的预处理器来转换__FILE__
在将Ruby源传递给解释器之前要做其他事情!
答案 1 :(得分:1)
你可以使用一个技巧。如果将块传递给方法,则可以使用块闭包来确定它的来源。类似的东西:
def filename(&blk)
blk.eval "__FILE__"
end
但同样,这意味着你必须传递一个阻止。
老实说,我想知道你想要完成什么,除了制作一些常见的核心扩展方法之外,这可能是你真正不想做的事情。