我正在研究宝石的内部结构,并遇到以下模式:
def foo
begin
return 'foo'
ensure
puts 'bar'
end
end
foo
这会将字符串'foo'
和'bar'
打印到STDOUT
。这是怎么发生的?我天真的理解是当你遇到return
语句时,然后从堆栈弹出调用并返回return指定的值。我想如果是这种情况,那么你就不能执行ensure
块了。显然,执行了ensure
块。我很好奇这是怎么回事。这种行为是如何实现的?
答案 0 :(得分:2)
这就是它在MRI中定义的方式,更具体地说是eval.c中的函数ensure
(我剪断了实际的实现,但实质上它只是生成一个Ruby执行上下文,执行块中的该上下文然后确保所有* Equivalent to <code>begin .. ensure .. end</code>.
*
* Calls the function \a b_proc with \a data1 as the argument,
* then calls \a e_proc with \a data2 when execution terminated.
* \return The return value of \a b_proc if no exception occurred,
* or \c Qnil if otherwise.
* \sa rb_rescue
* \sa rb_rescue2
* \sa rb_protect
* \ingroup exception
*/
VALUE
rb_ensure(VALUE (*b_proc)(ANYARGS), VALUE data1, VALUE (*e_proc)(ANYARGS), VALUE data2)
{
...
}
块一个接一个地运行:
parse.y
如果您对解析器决定如何调用此阵营感兴趣,请查看bodystmt
它是<xsl:strip-space elements="*"/>
<xsl:template match="market">
<xsl:for-each select=".//stock">
<xsl:value-of select="ancestor::market/category/type
|ancestor::market/items/element/name
|ancestor::market/items/element/type
|ancestor::market/items/element/color
|@cat
|@in" separator=", "/>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
规则的一部分。
答案 1 :(得分:1)
当你遇到
return
语句然后你
当 MRI 遇到return
声明时,它会 。一些口译员可能会打印"FOO"
到打印机;位于老板的房间里:)
从堆栈中弹出调用并返回
指定的值return
几乎。当 MRI 遇到return
语句时,会调用ensure
阻止(如果存在)并且然后会弹出关闭堆栈。
事情是没有强制性的规则,return
必须做一些特殊的事情,一成不变。 Ruby解释器(以及其他一些)就是这样做的。
答案 2 :(得分:0)
return
为方法赋值,即使执行过ensure
块。
例如:
def foo
begin
puts txt = 'foo'
return txt
ensure
puts 'bar'
end
puts txt = 'baz'
return txt
end
p foo
Puts&#34; foo&#34;和&#34; bar&#34;但不是&#34; baz&#34;。 foo方法也返回字符串&#34; foo&#34;。