Ruby for Newbies Iteratorer och block

Ruby är ett av de mest populära språk som används på webben. Vi har startat en ny screencast-serie här på Nettuts + som kommer att introducera dig till Ruby, liksom de stora ramar och verktyg som följer med Ruby-utvecklingen. I det här kapitlet ska vi prata om i block och iteratorer.


Komma ikapp

  • Lektion 1: Installera Ruby och Komma igång
  • Lektion 2: Variabler, datatyper och filer 
  • Lektion 3: Arbeta med klasser
  • Lektion 4: Conditionals och Loops
  • Lektion 5: Iteratorer och block

Visa skärmdump


Blocks

I den sista lektionen talade vi om loopar. Du kommer faktiskt inte använda loopar för ofta i Ruby, på grund av en funktion som heter block (och-som ett resultat av block-iteratorer). För att uppdatera ditt minne, kolla på de två följande metoden samtal (du kan prova detta i IRB):

namn = "Joe" name.reverse # => "eoJ" name.concat ("rörmokaren") # => "Joe the Plumber"

Som du vet är parenteserna efter metallsamtalet vanligtvis valfria. Vi lär oss idag när de behövs.

Så här är delarna av ett metodsamtal:

  • Föremålet som mottar metoden; namn ovan.
  • Pricken.
  • Metodnamnet; omvänd eller concat ovan.
  • Argumenten; " rörmokaren" i det andra exemplet ovan.
  • Kodblocket; håll dig stämd!

De första tre delarna krävs självklart. Argumenten och kodblocket är frivilliga. Vad är det här kodblocket? Titta på det här exemplet, och sedan diskuterar vi det:

webbplatser = ["net", "psd", "mobil"] webbplatser.map! gör | site | webbplats + = ".tutsplus.com" slutwebbplatser # => ["net.tutsplus.com", "psd.tutsplus.com", "mobile.tutsplus.com"]

I detta fall är matrisen webbplatser är mottagaren; metoden är Karta!. Nästa har vi blocket. Om blocket är på flera rader kan du använda sökorden do och slutet att avgränsa den. Om du lägger den på en enda rad kan du använda lockiga hängslen (dessa fungerar även för flera linjer).

Efter blockets öppning har vi blockparametrarna, inom rören ( | ). Vad detta verkligen beror på vilken metod du kör. Den vanligaste användningen av block är i iteratormetoder, så blockparametern blir det aktuella objektet i looping. Om det här låter ganska abstrakt, gör vi några exempel.


iteratorer

Vi börjar med att titta på iteratorerna av arrays, för att de är de vanligaste loopade sakerna.

Istället för att använda en för loop används det förmodligen varje:

webbplatser = ["net", "psd", "mobila"] webbplatser.each | site | sätter "# site .tutsplus.com" # net.tutsplus.com # psd.tutsplus.com # mobile.tutsplus.com

Det här är precis som att göra en för loop; en efter en, varje föremål i webbplatser kommer att tilldelas blockparametern webbplats; Då körs koden inuti blocket.

Om du är nyfiken, varje Metoden returnerar den ursprungliga matrisen.

Ibland vill du returnera ett värde från blocket. Det är inte svårt att göra, om du använder rätt metod.

# anta webbplatser ovanför webbplatser = sites.map do | s | "# s .tutsplus.com" slut

De Karta Metoden samlar in vilka värden som returneras från varje iteration av blocket. Därefter returneras en uppsättning av dessa värden från metoden. I det här fallet omfördelar vi webbplatser variabel till den nya matrisen.

Det finns dock ett bättre sätt att göra detta. Flera Ruby-metoder har dubbletter med utropstecken (eller bang); det betyder att de är destruktiva: de ersätter det värde de jobbar med. Så ovan kunde man göra så här:

sites.map! | site_prefix | "# site_prefix .tutsplus.com"

Nu, webbplatser kommer att vara en uppsättning värden som returneras från blocket.

Mer än bara arrays har iterator metoder. Nummer har en ganska cool gånger metod:

5 gånger gör | i | sätter "Loop nummer # i" slutet # Loop nummer 0 # Loop nummer 1 # Loop nummer 2 # Loop nummer 3 # Loop nummer 4

När du fortsätter kodning Ruby hittar du många användbara metoder som använder block. Låt oss nu se hur vi skapar egna block.


Byggklossar

Nu när du är bekant med att använda block, låt oss se hur man skriver metoder som utnyttjar dem. Här är två andra blockbitar som du inte har lärt dig än:

  • Blockparametrar är inte nödvändiga. du kan skriva ett block som inte använder dem.
  • Block kan vara valfria. Du kan skriva en funktion som fungerar med eller utan block.

Här är vad som händer du kallar en metod som tar ett block. Bakom kulisserna utför Ruby någon metodkod och ger sedan till blockkoden. Därefter returneras kontrollen till metoden. Låt oss kolla upp det.

Eftersom de flesta av de enkla iteratorfunktionerna är inbyggda i Ruby, kommer vi att skriva om en av dem. Låt oss göra varje metod på arrays:

klass Array def each2 i = 0; medan jag [i] ger själv [i] i + = 1 slutet självändaränden

Som du kan se är det bara en vanlig metod. Kom ihåg att inom en instansmetod, själv sökord hänvisar till förekomsten av klassen, i det här fallet, Array. Inuti metoden använder vi en stundslinga för att slingra över objekten i matrisen. Sedan, inuti slingan, använder vi avkastning nyckelord. Vi passerar det själv [i]; som kommer att bli blockparametern. Därefter ökar vi jag för slingan och fortsätt.

Om vi ​​ville ha den här metoden att returnera en uppsättning värden som blocket återvände, kunde vi bara fånga in det returnerade värdet av avkastning och returnera det, istället för själv, vi återvänder den matrisen.

klass Array def varje2_returning_new_values ​​i = 0; new_vals = []; medan jag själv [i] new_vals [i] = ger själv [i] i + = 1 sluta new_vals slutänden

Metoder, reviderad

Låt oss avsluta med att prata om metoder. Vi vet att med parentes är valfritt ... oftast. Här är när du behöver använda parentesen när metoden ringer.

Ibland har du både metodparametrar och ett block.

obj.some_method "param" | x | #block-kod här

Det jag just har gjort kommer inte att fungera. vi behöver använda parentes i det här fallet, för annars är blocket associerat med den sista parametern. Detta är bara fallet om du använder de krökta stagarna för att avgränsa blocket. om du använder do - slutet, parenteserna är inte nödvändiga.

Den andra gången parentes krävs är när du passerar en bokstavlig hash (inte en variabel som pekar på en hash) som den första parametern för metoden. Ruby kommer att tro att det är ett block, på grund av den lockiga häftstiftet

arr.push : name => "Andrew" # misslyckas! arr.push (: name => "Andrew") # Passerar