在开始期间会发生什么返回; ensure`?

时间:2018-05-16 10:25:09

标签: ruby

我正在研究宝石的内部结构,并遇到以下模式:

def foo
  begin
    return 'foo'
  ensure
    puts 'bar'
  end
end
foo

这会将字符串'foo''bar'打印到STDOUT。这是怎么发生的?我天真的理解是当你遇到return语句时,然后从堆栈弹出调用并返回return指定的值。我想如果是这种情况,那么你就不能执行ensure块了。显然,执行了ensure块。我很好奇这是怎么回事。这种行为是如何实现的?

3 个答案:

答案 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>&#xa;</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;。