Lokanir í Ruby: blokkir, procs og lambdas - Hver er munurinn?

Hægt er að skilgreina lokanir í Ruby sem búta af kóða sem hægt er að fara um eins og hluti og hægt er að framkvæma seinna. Þrjár mismunandi leiðir sem þú getur búið til lokun í Ruby er að fara í blokk til aðferðar, búa til proc og búa til lambda. Þegar við búum til lokun í Ruby mun þessi lokun bindast nærliggjandi gripum (eins og breytum, aðferðum, hlutum osfrv.) Sem eru að umfangi þegar lokunin var búin til. Ég ætla að ganga í gegnum mismunandi tegundir lokana í Ruby og ræða muninn á þeim.

Blokkir

Hægt er að skilgreina blokkir með do..end eða {..} og geta haft rök eins og sýnt er hér að neðan:

Sérhver aðferð í Ruby getur tekið valfrjálsan reit sem óbeina breytu eins og í dæminu hér að neðan:

Svo hvað þetta þýðir er í dæminu hér að ofan, við förum í reit óbeint á kveðjuaðferðina og til þess að hægt sé að kalla á reitinn verðum við að nota afrakstrarorðið. Við erum að fara inn í viðkomandi breytu manneskju (sem bendir á strenginn „Ashley“ sem var send í kveðjuaðferðina sem rifrildi) til að gefa sem rifrildi sem færst í færibreytuheiti blokkarinnar. Inni í reitnum setur „Hello # {name}!“ Framleiðsla Hello Ashley !. Við skulum sjá hvað gerist þegar við færum ekki rök fyrir reitinn.

Í dæminu hér að ofan erum við ekki að fara í rifrildi til að skila sem þýðir að engin rök eru send í reitinn sem samþykkir eina breytu. Furðu, ArgumentError var ekki skilað. Þetta er vegna þess að blokkir framfylgja ekki rifrildi. Í staðinn, ef við færum ekki rök fyrir reitinn þegar reiturinn samþykkir færibreytu, mun færibreytan vísa til nuls. Þar sem engin rök voru færð fyrir heiti lokabreytunnar bendir staðbundna breytan á nul og það er ástæðan fyrir að framleiðsla kveðjuaðferðarinnar var Hello! sem hefur auka pláss eftir Halló þar sem nafnið hefði átt að vera.

Procs

Það eru tvær leiðir til að búa til procs eins og sýnt er hér að neðan:

Í fyrra dæminu erum við að búa til Proc hlut með því að kalla nýju aðferðina í Proc bekkinn og fara í reit sem rök. Í seinna dæminu getum við búið til proc með því að kalla proc aðferðina frá Kernel einingunni og fara í reit sem rök.

Til þess að kalla fram reitinn verðum við að hringja í kallaðferðina á proc hlutnum.

Í dæminu hér að ofan köllum við hringiaðferðina á proc1 sem bendir á proc hlutinn. „Ashley“ er síðan sent inn sem rök fyrir kallaðferðinni, sem færst við færibreytuheiti blokkarinnar og Halló Ashley! er prentað.

Dæmið hér að neðan sýnir hvað gerist þegar við berum ekki rök fyrir proc.

Þegar hringiaðferðin er kölluð á proc hlutinn proc1, gefum við ekki rök. Þetta þýðir að engin rök voru færð fyrir heiti færibreytunnar. Engin ArgumentError var vakin vegna þess að procs deila sömu arity reglum og blokkir og framfylgja ekki rifrildi. Rétt eins og blokkir, ef engin rök eru færð yfir við færibreytuna, þá verður þeim færibreytum úthlutað til núll. Þetta er ástæðan fyrir því að við fáum framleiðsluna Halló !.

Lambdas

Það eru tvær leiðir til að búa til lambadas eins og sýnt er hér að neðan:

Í fyrra dæminu getum við búið til lambda með því að kalla lambda aðferðina frá Kernel einingunni og fara í reit sem rök. Í öðru dæminu erum við að búa til lambda með því að nota syntaktískan sykur Ruby. Í dæminu erum við að nota -> og setja síðan blokkarstærðina innan sviga og förum síðan í reitinn. Þannig að aðalmunurinn á tveimur mismunandi leiðum til að búa til lambda er að í fyrra dæminu eru blokkarstærðirnar inni í reitnum og í öðru dæminu eru blokkarstærðirnar í sviga á eftir -> í staðinn fyrir inni í reitnum.

Eitt sem þarf að hafa í huga er að til að búa til lambda getum við ekki gert þetta:

Ástæðan fyrir því er að lambdasar eru í raun ekki Lambda hluti, þeir eru Proc hlutir. Helsti munurinn á procs og lambdasum er sú staðreynd að þau hafa mismunandi arity reglur.

Þar sem lambdas eru Proc hlutir getum við kallað kallaðferðina á lambda og blokkin verður framkvæmd. Í fyrsta dæminu hér að ofan köllum við hringiaðferðina á lambda1 og gefum rökin 'Ashley' sem fær framhjá heiti lokabreytunnar og setur „Halló # {nafn}!“ framleiðsla Halló Ashley !. Í öðru dæminu er lambda1 kallað án þess að færa rök fyrir kallaðferðinni og þar sem reiturinn tekur eina breytu er ArgumentError skilað. Þetta sýnir að ólíkt procs og kubbum framfylgja lambdasar rifrildi.

Einn síðastur hlutur ...

Annað sem aðgreinir blokkir, procs og lambdas er hvernig þeir takast á við aftur leitarorð.

Blokkir

Þegar ég keyri kóðann hér að neðan:

Ég fæ þessi villuboð:

óvænt endurkoma (LocalJumpError)

Svo, venjulega þegar aðferðin skilar sér í reitinn, þá er það sem er að gerast að framkvæmd áætlunarinnar stekkur frá aðferðarútfærslunni yfir í reitinn. Almennt skila forrit LocalJumpError þegar við höfum ávöxtun í framkvæmd aðferðarinnar en aldrei farið í blokk til aðferðarinnar. Þetta gerir það að verkum að forritið hoppar frá aðferðaframleiðslunni yfir í engan blokka sem er ástæða þess að villan kemur upp. Það var engin hindrun til að stökkva og þess vegna LocalJumpError villan!

Þetta er sama ástæða þess að við fengum LocalJumpError í dæminu hér að ofan. Þegar aðferðin skilaði sér að reitnum hoppaði framkvæmd áætlunarinnar að reitnum þar sem hún rakst á aftur leitarorð. Þetta olli því að framkvæmd áætlunarinnar stöðvaðist snögglega án þess að hoppa aftur til aðferðarútfærslunnar og þess vegna var LocalJumpError skilað.

Procs

Þegar ég keyri kóðann hér að neðan:

Ég fæ engar villur eins og ég gerði í lokadæminu. Þegar búið er að hringja í proc og skila „halló“ er metið inni í reitnum stöðvast framkvæmd forritsins og „halló“ er skilað frá proc_example aðferðinni. Takið eftir að síðasta lína aðferðarinnar „bless“ var aldrei metin. Ástæðan fyrir þessu er sú að procs snúa aftur úr reitnum sjálfum sem veldur því að framkvæmd aðferðarinnar stöðvast.

Lambdas

Þegar ég keyri kóðann hér að neðan:

Framkvæmd áætlunarinnar stöðvaði ekki fyrir tímann. Þegar hringt var í lambda1 og kallað var á reitinn stöðvaði framkvæmd forritsins ekki og skilaði sér innan úr reitnum eins og í proc dæminu. Í staðinn heldur framkvæmd dagsins áfram og „bless“ var skilað með lambda_dæmi aðferðinni. Svo þegar aftur leitarorð er metið inni í reitnum, þá mun lambda hunsa aftur leitarorð og framkvæmd forritsins heldur áfram.

Lokanir í Ruby geta verið erfiðar og ef ég hef misst af einhverju í bloggfærslunni minni um lokanir ekki hika við að deila!