Ruby中的語句中斷和返回

來源:互聯網
上載者:User

標籤:

`return`,`break`,`next` 這幾個關鍵字的使用都涉及到跳出範圍的問題,而他們的不同 則在於不同的關鍵字跳出去的目的範圍的不同,因為有代碼塊則導致有一些地方需要格外注意。***return***常用方式通常情況下的`return`語句和大家理解的意思是相同的。```Rupy def m1 param if param == 1 return ‘returned 1‘ end ‘returned default value‘#根據Ruby語言規範,最後一條執行語句的結果將作為傳回值返 ,retu rn是可選的 end m1(1) # => returned 1 m1(2) # => returned default value```在有異常捕獲的`ensure`時,情況會稍有不同:``` def m1 ‘return default‘ ensure puts ‘I am sure that it will be here!‘ end m1 # => return default```像這種情況,在`ensure`語句之前,無論是否顯示用`return`來返回,m1方法都會返回`ensure`之前的值, `ensure`語句只是確保之後的代碼塊`puts ‘I am sure that it will be here!‘`執行,但是不會從這裡返回。 如果在ensure語句中顯示的用`return`來傳回值時,情況就不一樣了。樣本如下:``` def m1 return ‘return default‘ ensure return ‘I am sure that it will be here!‘ end m1 # => I am sure that it will be here!```無論在ensure之前是否顯示返回,都只會返回`ensure`之後的值。在有代碼塊幹預的情況下,又會有所不同:``` def m1 p ‘start ... ‘ proc do p ‘block start‘ return p ‘block end‘ end.call p ‘end ... ‘ end m1 # 輸出結果: # # "start ... " # "block start"```這個應該是在預料之中的,再看下一個:``` def m1 p ‘start ... ‘ -> do p ‘block start‘ return p ‘block end‘ end.call p ‘end ... ‘ end m1 # 輸出結果: # # "start ... " # "block start" # "end ... "```這裡多了一行`"end ... "`,原因何在?這就是Proc和Lambda最大的區別,在他們之中的`return` 語句跳出去的目的範圍不同,Proc會直接跳出整個方法的調用,而Lambda只會跳出自身的範圍, 返回到方法中繼續執行,這一點需要格外注意。(在break中,Proc和Lambda的跳出方式和return是一樣的,後面就不再贅述了。)***break***先來看一個簡單的小例子:``` result = [1, 2, 3, 4, 5].map do |i| i * 2 end p result # => [2, 4, 6, 8, 10]```這個沒什麼奇怪的,那麼看看下面這個,來猜猜它的輸出結果是什嗎?``` result = [1, 2, 3, 4, 5].map do |i| break if i > 3 i * 2 end # FLAG p result```是`[1, 2, 3, nil, nil]`?還是`[1, 2, 3]`?還是什嗎?答案是`nil`,因為執行`break`後,直接跳到了`FLAG` ,也就是跳出了`map`方法,而`map`方法中的語句並沒有執行完,導致沒有任何傳回值,為了驗證這個想法是正確的,我們 可以利用Ruby語言的`break`可以帶傳回值的特性來驗證一下:``` result = [1, 2, 3, 4, 5].map do |i| break ‘returned break‘ if i > 3 i * 2 end p result # => "returned break"```這裡可以證明我們的猜測是正確的。雖然上面說明了這個問題,但是應該還不是非常容易理解,我們自己定義 一個代碼塊,再來說明一下:``` def m1 p ‘start in m1 ... ‘ m2 do # 代碼塊 p ‘start in block in m1 ... ‘ p ‘end in block in m1 ... ‘ end p ‘end in m1 ... ‘ end def m2 &block p ‘start in m2 ... ‘ block.call p ‘end in m2 ... ‘ end m1 # 輸出結果: # # "start in m1 ... " # "start in m2 ... " # "start in block in m1 ... " # "end in block in m1 ... " # "end in m2 ... " # "end in m1 ... "```然後我們在m1中的block中添加`break`,來看看執行結果:``` def m1 p ‘start in m1 ... ‘ m2 do # 代碼塊 p ‘start in block in m1 ... ‘ break p ‘end in block in m1 ... ‘ end p ‘end in m1 ... ‘ end def m2 &block p ‘start in m2 ... ‘ block.call p ‘end in m2 ... ‘ end m1 # 輸出結果: # # "start in m1 ... " # "start in m2 ... " # "start in block in m1 ... " # "end in m1 ... "```可以看到代碼塊的最後一行代碼沒有執行,m2的最後一行也沒有執行,就是因為這一行沒有執行,導致 `break`的第二個例子中的map沒有返回任何值。總結一下,代碼塊中的`break`會直接跳出調用的方法(m2), 而在聲明代碼塊的方法(m1)中繼續執行此方法(m1)中剩下的語句。***next***next關鍵字類似其他語言中的`continue`,它的工作方式基本和`continue`類似。``` def m1 p ‘start in m1 ... ‘ m2 do # 代碼塊 p ‘start in block in m1 ... ‘ next p ‘end in block in m1 ... ‘ end p ‘end in m1 ... ‘ end def m2 &block p ‘start in m2 ... ‘ block.call p ‘end in m2 ... ‘ end m1 # 輸出結果: # # "start in m1 ... " # "start in m2 ... " # "start in block in m1 ... " # "end in m2 ... " # "end in m1 ... "```只是略過了代碼塊的最後一行代碼,這就是`next`的工作方式了。我們再來看看`break`的那個例子如果 用`next`來寫,看看結果是什嗎?如果你完全理解了上面所寫的,相信你已經能在大腦中計算出結果了:``` result = [1, 2, 3, 4, 5].map do |i| next if i > 3 i * 2 end p result # => [2, 4, 6, nil, nil]````next`語句也能帶傳回值:``` result = [1, 2, 3, 4, 5].map do |i| next ‘next‘ if i > 3 i * 2 end p result # => [2, 4, 6, "next", "next"]``` ***其他***對於`return`,在方法中,代碼塊中都可以使用,而`break`和`next`只能在代碼塊中使用(迴圈結構中 也可以使用,但是一般它也是用代碼塊的形式來表示),如果在方法中調用兩者會提示法錯誤,也就是:``` def m1 return # OK break # Invalid break, compile error (SyntaxError) next # Invalid next, compile error (SyntaxError) end```***結論***`return` 大部分情況下和其他語言無異,需要注意在`ensure`以及`Proc`和`Lambda`兩種不同的 代碼塊中的細節問題。`break` 在有方法嵌套調用中的代碼塊中需要注意,它總是返回到調用代碼塊方法的方法中(有點繞)。`next` 最老實,基本不需要注意什麼。最後就是,不只是`return`能傳回值,`break`和`next`都能傳回值。--------------**本文系[OneAPM](http://oneapm.com/index.html?utm_source=Common&utm_medium=Articles&utm_campaign=TechnicalArticles&from=matefijuno)工程師編譯整理。OneAPM是中國基礎軟體領域的新興領軍企業,能協助企業使用者和開發人員輕鬆實現:緩慢的程式碼和SQL語句的即時抓取。想閱讀更多技術文章,請訪問OneAPM[官方技術部落格](http://code.oneapm.com/?hmsr=media&hmmd=&hmpl=&hmkw=&hmci=)。**

Ruby中的語句中斷和返回

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.