[轉(zhuǎn)]淺談Ruby中的block, proc, lambda, method object的區(qū)別

本文主要介紹了ruby開發(fā)中的比較容易混淆的幾個概念空凸,并以簡單示例的形式展現(xiàn)他們之間的區(qū)別,明白了這些區(qū)別之后馋艺,在今后的開發(fā)中可以準確并優(yōu)雅的使用它們召娜。

當大家在百度中搜索“block proc lambda”的時候掠抬,會出來很多關(guān)于這幾個概念之間區(qū)別的介紹,既然搜索結(jié)果中已經(jīng)有了這些介紹,那為什么還要寫這篇文章?

相信看過百度搜索結(jié)果中排名靠前的幾篇文章的同學私蕾,都會發(fā)現(xiàn)其實這些文章并沒有很好的說明他們之間區(qū)別是什么,大多只是介紹各自的用法胡桃,加上些許的區(qū)別踩叭,即使個別介紹了一些區(qū)別,也不夠系統(tǒng)翠胰,不夠深入懊纳。

正是基于上述原因,才醞釀了本文亡容。本文以簡單示例的方式,詳細的介紹了它們之間的區(qū)別冤今。相信您閱讀完本文闺兢,一定會豁然開朗,并在今后的開發(fā)中準確并優(yōu)雅的使用它們。

由于時間屋谭,個人能力水平等有限脚囊,本文難免有錯誤或缺失之處,歡迎不吝指出桐磁。

block & proc

在介紹它們的區(qū)別之前悔耘,我們先來看一段有關(guān)block的簡單使用方法:

def use_yield

yield

end

use_yield do

puts'use yield'

end

def use_block_call(&block)

block.call

end

use_block do

puts'use block call'

end

以上介紹了兩種在函數(shù)中使用block的方式,第一種是通過yield來使用block我擂,另外一種則是通過block.call來使用block衬以。

proc全稱為procedure,中文翻譯為過程校摩,步驟看峻。關(guān)于block和proc的區(qū)別,我們先來看一個簡單的示例衙吩。

def what_am_i(&block)

block.class

end

puts?what_am_i?{}#?=<?Proc

定義一個函數(shù)what_am_i并接受一個block互妓,執(zhí)行體中打印了block的類型,從執(zhí)行的結(jié)果我們看到block的類型為proc,即說明block為proc的一種坤塞。

block和proc之間的區(qū)別主要有兩個:一是proc可以重復使用冯勉,如果某個block將在多個地方被用到,則我們可以將其定義為proc摹芙。另外一個區(qū)別就是當某個函數(shù)需要執(zhí)行多個閉包的時候灼狰,此時我們就無法使用block而只有使用proc或其他的閉包。

示例如下瘫辩,在執(zhí)行某個具體的操作的前后伏嗜,調(diào)用了我們自己的proc。

def action(code)

code[:before].call

puts'processing...'

code[:after].call

end

action:before=>Proc.new{puts'before?action'},

:after=>Proc.new{puts'after?action'}

proc & lambda

關(guān)于proc和lambda的區(qū)別伐厌,我們先來看一個簡單的例子承绸。

def args(code)

code.call'one','two'

end

args Proc.new{?|a,b|?puts?a,b}

args?lambda?{|a,b|?puts?a,b}

上述示例,第一眼看去發(fā)覺lambda和proc之間沒什么區(qū)別或者很難發(fā)現(xiàn)它們的區(qū)別是什么挣轨。

接下來军熏,我們對上述示例做一下簡單的修改,我們將之前的接受兩個參數(shù)修改為三個卷扮,看看會發(fā)生什么情況荡澎。

def args(code)

code.call'one','two'

end

args Proc.new{?|a,b,c|?puts?a,b,c}

args?lambda?{|a,b,c|?puts?a,b,c}#?=<?wrong?number?of?arguments?(2?for?3)?(ArgumentError)

運行修改后的示例,發(fā)現(xiàn)lambda閉包出錯了晤锹,出錯的信息為摩幔,錯誤的參數(shù)個數(shù)。

至此鞭铆,我們很快就發(fā)現(xiàn)了它們之間的一個區(qū)別是或衡,lambda會檢查參數(shù)的個數(shù),而proc則不會,proc默認將缺失的參數(shù)視為nil封断,并繼續(xù)執(zhí)行代碼斯辰,這是為什么呢?在本節(jié)的最后坡疼,我們會道出這其中的緣由彬呻。

在了解到它們的第一個區(qū)別之后,接下來我們再來看一個示例柄瑰。

def proc_return?

Proc.new{return'Proc.new'}.call

puts'proc_return?method?finished'

end

def lambda_return

lambda?{return'lambda'}.call

puts'lambda_return?method?finished'

end

puts?proc_return#?=<?Proc.new

puts?lambda_return#?=<?lambda_return?method?finished

這個示例非常的簡單闸氮,我們定義了兩個函數(shù)proc_return以及l(fā)ambda_return。這兩個函數(shù)一個用proc實現(xiàn)狱意,另外一個用lambda實現(xiàn)湖苞,執(zhí)行體都只有一行代碼,就是返回一段字符串详囤。

執(zhí)行的結(jié)果出乎我們的意料财骨,proc并未執(zhí)行return之后的代碼,而lambda執(zhí)行了return之后的代碼藏姐。

綜上所述隆箩,我們得出了proc和lambda的兩個重要區(qū)別,一是lambda會進行參數(shù)個數(shù)的檢查而proc則不會羔杨,另外lambda會執(zhí)行return之后的代碼而proc則不會捌臊。

為什么會出現(xiàn)上述情況,本質(zhì)的原因在于兜材,proc只是一段嵌入的代碼片段而lambda則是匿名函數(shù)理澎,正因為是匿名函數(shù),所以會檢查函數(shù)調(diào)用參數(shù)曙寡,并在函數(shù)調(diào)用結(jié)束之后糠爬,繼續(xù)執(zhí)行后面的代碼,而proc由于是嵌入的一段代碼片段举庶,在執(zhí)行完return語句后执隧,就已經(jīng)返回,所以不再執(zhí)行之后的代碼户侥。

lambda & method object

def greeting

puts'hello,?method?object'

end

method(:greeting).call

lambda {puts'hello,?lambda'}.call

lambda和method object的用法基本一致镀琉,其唯一的區(qū)別在于lambda為匿名函數(shù),而method object為命名函數(shù)蕊唐。

總結(jié)

關(guān)于block,proc,lambda, method object這四者之間的區(qū)別可總結(jié)為以下:

block和proc本質(zhì)上是一段嵌入的代碼塊屋摔,并非函數(shù)。而lambda和method object都是函數(shù)替梨,只不過lambda是匿名函數(shù)钓试,而method object為命名函數(shù)署尤。

從本質(zhì)上理解了它們的區(qū)別,我們在今后的開發(fā)中就會正確且優(yōu)雅的運用它們亚侠。

引用

[1]http://www.reactive.io/tips/2008/12/21/understanding-ruby-blocks-procs-and-lambdas/

相關(guān)代碼

來自:http://my.oschina.net/gschen/blog/325546

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市俗扇,隨后出現(xiàn)的幾起案子硝烂,更是在濱河造成了極大的恐慌,老刑警劉巖铜幽,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件滞谢,死亡現(xiàn)場離奇詭異,居然都是意外死亡除抛,警方通過查閱死者的電腦和手機狮杨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來到忽,“玉大人橄教,你說我怎么就攤上這事〈” “怎么了护蝶?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長翩迈。 經(jīng)常有香客問我持灰,道長,這世上最難降的妖魔是什么负饲? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任堤魁,我火速辦了婚禮,結(jié)果婚禮上返十,老公的妹妹穿的比我還像新娘妥泉。我一直安慰自己,他們只是感情好吧慢,可當我...
    茶點故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布涛漂。 她就那樣靜靜地躺著,像睡著了一般检诗。 火紅的嫁衣襯著肌膚如雪匈仗。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天逢慌,我揣著相機與錄音悠轩,去河邊找鬼。 笑死攻泼,一個胖子當著我的面吹牛火架,可吹牛的內(nèi)容都是我干的鉴象。 我是一名探鬼主播,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼何鸡,長吁一口氣:“原來是場噩夢啊……” “哼纺弊!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起骡男,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤淆游,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后隔盛,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體犹菱,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年吮炕,在試婚紗的時候發(fā)現(xiàn)自己被綠了腊脱。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡龙亲,死狀恐怖陕凹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情俱笛,我是刑警寧澤捆姜,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站迎膜,受9級特大地震影響泥技,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜磕仅,卻給世界環(huán)境...
    茶點故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一珊豹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧榕订,春花似錦店茶、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至两嘴,卻和暖如春丛楚,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背憔辫。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工趣些, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人贰您。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓坏平,卻偏偏與公主長得像拢操,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子舶替,可洞房花燭夜當晚...
    茶點故事閱讀 45,440評論 2 359

推薦閱讀更多精彩內(nèi)容

  • I recommend executing this file, then reading it alongsid...
    YongpingZhao閱讀 1,744評論 0 0
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理令境,服務(wù)發(fā)現(xiàn),斷路器顾瞪,智...
    卡卡羅2017閱讀 134,693評論 18 139
  • //Clojure入門教程: Clojure – Functional Programming for the J...
    葡萄喃喃囈語閱讀 3,680評論 0 7
  • &:to_i是一個block展父,block不能獨立存在,同時你也沒有辦法直接存儲或傳遞它玲昧,必須把block掛在某個方...
    AQ王浩閱讀 337評論 0 0
  • 又是忙叨叨的一天吶,一句話篮绿,又沒學習孵延,又有一屁股事情等著我。上午提著電腦亲配,拿著書尘应,好不容易到達圖書館,發(fā)現(xiàn)除了那本...
    獨行者87閱讀 149評論 0 1