在哪里可以找到像 instance_exec 这样的 Native Ruby 源代码?
Posted
技术标签:
【中文标题】在哪里可以找到像 instance_exec 这样的 Native Ruby 源代码?【英文标题】:where to find Native Ruby source code such as instance_exec? 【发布时间】:2021-01-13 14:26:04 【问题描述】:我知道有函数“method(:instance_exec).source_location”来查找源代码,但仅适用于 gems 中的代码。但在这种特殊情况下它返回 null,因为该方法来自本机 ruby。我在谷歌搜索,但我无法找到这是写在哪里。 在我的特殊情况下,我想更好地了解 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 + Go To + Implementation 只显示我
def instance_exec(*args)
# This is a stub implementation, used for type inference (actual method behavior may differ)
yield
end
【问题讨论】:
ruby-doc.org/core-2.7.0/BasicObject.html#method-i-instance_exec 谢谢,但提供的链接解释了如何使用该方法。我正在寻找它在引擎盖下的作用,它的源代码。这就是我对“它的实施”的意思,而不是如何使用它。我的目标是以某种方式扩展它,这样我不仅可以传递块的参数,还可以设置其范围的变量 github.com/ruby/ruby/blob/v2_7_1/vm_eval.c#L2003-L2033 – 不确定 C 代码将如何提供帮助。 要在块中拥有方法divisor
,您必须将其添加到self
所指的对象,即instance_exec
的接收者
【参考方案1】:
我知道有函数“method(:instance_exec).source_location”来查找源代码,但只适用于gems中的代码。
那不是真的。 Method#source_location
适用于不在 gems 中的方法:
module Foo
def bar; end
end
p Foo.instance_method(:bar).source_location
#=> ['test.rb', 2]
这里没有宝石。事实上,如果我根本不使用任何文件,它甚至可以工作,只需在命令行上使用ruby -e
;在这种情况下,结果将是 ['-e', 2]
。
另一方面,如果没有 Ruby 源代码,那么它会返回 nil
即使对于 gems。
Method#source_location
的返回值与方法是否来自 gem 无关,唯一重要的是是否有 Ruby 源可以定位。 p>
但在这种特殊情况下它返回 null,因为该方法来自原生 ruby。
它不应该返回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, Object[] arguments, NotProvided block) throw new RaiseException(getContext(), coreExceptions().localJumpError("no block given", this));
【讨论】:
以上是关于在哪里可以找到像 instance_exec 这样的 Native Ruby 源代码?的主要内容,如果未能解决你的问题,请参考以下文章
我可以将一个本身期望一个块的块传递给 ruby 中的 instance_exec 吗?
在Outlook 2019中,我在哪里可以找到Outlook日历权限?