[英]Are there unintended consequences of Ruby's `begin … end` without `rescue` used as a code block?
我偶爾會看到ruby中使用的begin...end
塊,而沒有進行任何rescue
, else
, ensure
等語句之間。 例如:
foo = begin
whatever = 3
"great"
42
end
看來,編碼器的意圖是僅出於其塊分組質量而使用begin...end
塊(就好像begin
是do
)。 我個人認為這種用法違反了最少驚訝的原則( 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
將分配給變量a
, putobject, 2
)。 與a = 5; c = 6
相比,其唯一的副作用a = 5; c = 6
a = 5; c = 6
是dup
指令,這意味着方法的堆棧大小將增加1個插槽。 但這並不是特別重要,因為它僅在解釋器位於此特定方法內部時才起作用,並且無論如何都將為堆棧保留內存,因此這僅意味着堆棧指針將比原來減少1。 因此,基本上沒有任何變化。 啟用優化后,即使dup
也可能消失。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.