繁体   English   中英

没有将`rescue`用作代码块的Ruby的`begin…end`会有意外的后果吗?

[英]Are there unintended consequences of Ruby's `begin … end` without `rescue` used as a code block?

我偶尔会看到ruby中使用的begin...end块,而没有进行任何rescueelseensure等语句之间。 例如:

foo = begin
   whatever = 3
   "great"
   42
end

看来,编码器的意图是仅出于其块分组质量而使用begin...end块(就好像begindo )。 我个人认为这种用法违反了最少惊讶的原则( begin对我意味着异常处理)。

以这种方式使用begin...end有任何意外的后果吗? begin...end块是否有任何语义差异(可能在异常处理中?),使这种用法很危险?

Ruby的语法令人难以置信,如果在这里等待等待,我就不会感到惊讶。

如果我想给变量赋值,但有时我必须先计算要赋值,我有时会用到它。 这样可以使代码更加整洁。 我认为这是用户的偏爱。 基本上您是在说:我为foo分配了一些东西,但是为了获得所需的值,我首先需要做一些事情。 做备忘录时特别有用,因此

if @cache.nil?
  do_something!
  @cache = read_value
end

你可以做

@cache ||= begin
  do_something!
  read_value
end

您在这里利用的是Ruby解释器有一个堆栈,每个表达式通常会将某些内容压入堆栈或从堆栈中取出内容。 分配只是从堆栈中取出最后一个东西并分配它(在这种情况下,这是开始/结束的最后一行)。 很多时候了解这一点(Ruby中的堆栈方法)可能会很有用。

我认为它不会给您带来什么意外的惊喜,我认为您是否愿意使用它都是用户的首选。

通过查看它在Ruby MRI 1.9中生成的字节码指令,您可以看到它没有做任何意外的事情:

 RubyVM::InstructionSequence::compile("c = begin; a = 5; 6; end").to_a

 [:trace, 1],
 [:trace, 1],
 [:putobject, 5],
 [:setlocal, 2],
 [:trace, 1],
 [:putobject, 6],
 [:dup],
 [:setlocal, 3],
 [:leave]

跟踪仅用于堆栈跟踪,您可以忽略它。 Dup复制堆栈中的最后一个项目。 在此示例中,局部变量a的数量为2 ,局部变量c的数量为3 (因此putobject, 2将分配给变量aputobject, 2 )。 a = 5; c = 6相比,其唯一的副作用a = 5; c = 6 a = 5; c = 6dup指令,这意味着方法的堆栈大小将增加1个插槽。 但这并不是特别重要,因为它仅在解释器位于此特定方法内部时才起作用,并且无论如何都将为堆栈保留内存,因此这仅意味着堆栈指针将比原来减少1。 因此,基本上没有任何变化。 启用优化后,即使dup也可能消失。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM