簡體   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