微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Ruby的“begin … end”是否有意想不到的后果,而没有“rescue”用作代码块?

我偶尔会看到在ruby中使用的最终块,没有任何的救援,否则,确保等等.例如:
foo = begin
   whatever = 3
   "great"
   42
end

编码器的意图似乎是使用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,[:putobject,5],[:setlocal,2],6],[:dup],3],[:leave]

跟踪只是堆栈跟踪,你可以忽略它. Dup重复堆栈上的最后一个项目.在本示例中,局部变量a的数量为2,局部变量c的数量为3(因此,putobject,2将分配给变量a等).这与a = 5相比唯一的副作用; c = 6是dup指令,这意味着您的方法的堆栈大小将大于1个插槽.但是这并不是特别重要,因为它只有解释器在这个特定的方法中才有效果,而且堆栈的内存是预先保留的,所以这只意味着堆栈指针将比其它方式递减1.所以基本上没有变化.即使是优化也可能会消失.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐