如何解决在哪里可以找到本机Ruby源代码例如instance_exec?
我知道有功能“ method(:instance_exec).source_location”来查找源代码,但仅适用于gems中的代码。但是在这种特殊情况下它返回null,因为该方法来自本机红宝石。我正在谷歌搜索,但是我找不到这写在哪里。 在我的特定情况下,我想更好地了解instance_exec如何更改proc范围的值
去切线,我想去上大学
precondition { divisor != 0 }
postcondition { |result| result * divisor == dividend}
def divide(dividend,divisor)
dividend / divisor
end
我知道instance_exec在proc范围内更改了'self'值。我想在运行它时在{ divisor != 0 }
proc范围内添加“除数”,并且我认为读取instance_exec的实现将非常有帮助。
既然是上大学,我就不能使用任何宝石来做到这一点,只能使用标准红宝石
PS right_click +转到+仅显示实现
def instance_exec(*args)
# This is a stub implementation,used for type inference (actual method behavior may differ)
yield
end
解决方法
我知道可以使用函数“ method(:instance_exec).source_location”来查找源代码,但仅适用于gems中的代码。
那不是事实。 Method#source_location
适用于非gem的方法:
module Foo
def bar; end
end
p Foo.instance_method(:bar).source_location
#=> ['test.rb',2]
这里没有宝石。实际上,如果我根本不使用任何文件,甚至在命令行上使用ruby -e
,它甚至都可以工作。在这种情况下,结果将为['-e',2]
。
另一方面,如果没有 Ruby源,那么即使是宝石,它也会返回nil
。
Method#source_location
的返回值与该方法是否来自gem无关,唯一重要的是,甚至 是否也可以找到Ruby源。
但是在这种特殊情况下,由于该方法来自本机红宝石,因此它返回null。
它不应该返回null
,它应该返回两个元素的数组或nil
,但不要返回null
。如果确实如此,那么您的Ruby安装似乎已经发生了一些严重的问题。
我正在谷歌搜索,但是我找不到这写在哪里。
它将位于您正在使用的Ruby实现的源代码中。您尚未指定使用的是哪种实现,因此我无法确切告诉您,但这是一些示例:
在Rubinius中,它是在core/basic_object.rb
中实现的:
def instance_exec(*args,&prc) raise ::LocalJumpError,"Missing block" unless block_given? env = prc.block return prc.ruby_method.call(*args) if prc.ruby_method lexical_scope = env.lexical_scope if ::ImmediateValue === self lexical_scope = lexical_scope.using_disabled_scope else sc = ::Rubinius::Type.object_singleton_class(self) lexical_scope = lexical_scope.using_current_as(sc) end return env.call_under(self,lexical_scope,true,*args) end
在TruffleRuby中,它是在src/main/java/org/truffleruby/core/basicobject/BasicObjectNodes.java
中实现的:
@CoreMethod(names = "instance_exec",needsBlock = true,rest = true) public abstract static class InstanceExecNode extends CoreMethodArrayArgumentsNode { public static InstanceExecNode create() { return InstanceExecNodeFactory.create(null); } @Child private CallBlockNode callBlockNode = CallBlockNode.create(); abstract Object executeInstanceExec(Object self,Object[] args,RubyProc block); @Specialization protected Object instanceExec(Object receiver,Object[] arguments,RubyProc block) { final DeclarationContext declarationContext = new DeclarationContext( Visibility.PUBLIC,new SingletonClassOfSelfDefaultDefinee(receiver),block.declarationContext.getRefinements()); return callBlockNode .executeCallBlock(declarationContext,block,receiver,block.block,arguments); } @Specialization protected Object instanceExec(Object receiver,NotProvided block) { throw new RaiseException(getContext(),coreExceptions().localJumpError("no block given",this)); } }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。