Ruby on Rails Studiegids Blokken, Procs en Lambda's

Ruby is een taal met een reeks krachtige functies - de krachtigste zijn waarschijnlijk Blokken, Procs en Lambda's. Kort gezegd, met deze functies kunt u code aan een methode doorgeven en die code op een later tijdstip uitvoeren. Ondanks het regelmatig gebruik van deze functies, begrijpen veel ontwikkelaars de subtiele verschillen tussen hen niet volledig.

Studiegidsen: Wanneer u solliciteert voor een programmeeropdracht, krijgt u vaak een quiz te zien die van plan is uw niveau van kennis en ervaring in een bepaald onderwerp te bepalen. De verschillende artikelen in deze serie bieden verkorte oplossingen voor de vragen die u zou verwachten bij dergelijke tests.

Blocks

Een blok is een code die impliciet wordt doorgegeven aan een methode door het gebruik van accolades, ..., of doe ... einde syntaxis. Het is gebruikelijk om te gebruiken ... voor blokken met één regel, en doe ... einde voor blokken met meerdere regels. De volgende blokken zijn bijvoorbeeld functioneel hetzelfde:

array = [1,2,3,4] array.map! do | n | n * n end => [1, 4, 9, 16] array = [1,2,3,4] array.map! | n | n * n => [1, 4, 9, 16]

De magie achter een blok is het opbrengst trefwoord; het verdedigt de uitvoering van de aanroepende methode om het blok te evalueren. Het resultaat van het blok, indien aanwezig, wordt vervolgens geëvalueerd met de resterende code in de methode. De opbrengst statement kan ook parameters accepteren, die vervolgens binnen het blok worden doorgegeven en geëvalueerd. Dit samen verbinden, een eenvoudig voorbeeld van de kaart! bovenstaande methode zou de volgende zijn:

class Array def map! self.each_with_index do | value, index | self [index] = opbrengst (waarde) einde end end

Deze eenvoudige weergave van kaart! roept de each_with_index methode en vervangt het item op de gegeven index met het resultaat van het blok. Hoewel dit een triviaal voorbeeld van blokgebruik is, helpt het om te laten zien opbrengstzijn kracht. Het gebruik van blokken in Ruby is eindeloos, en we gebruiken ze vaak in onze code.


ontwerp en bouw

Het bovenstaande voorbeeld laat een beperkte beperking van blokken zien: ze zijn syntaxis en wegwerpbaar. We moeten blokken opnieuw typen telkens wanneer we ze opnieuw gebruiken in verschillende arrays, maar we kunnen een blok opslaan voor later gebruik door het Ruby Proc-object te gebruiken. We kunnen een Proc opslaan in een variabele en deze vervolgens expliciet doorgeven aan elke methode die een opvraagbaar object accepteert. Herschrijven van het bovenstaande voorbeeld als een Proc ziet er als volgt uit:

number_squared = Proc.new | n | n * n

Laten we onze aanpassen kaart! methode om het Proc-object te accepteren en aanroepen:

class Array def map! (proc_object) self.each_with_index do | value, index | self [index] = proc_object.call (waarde) end-end end-array = [1,2,3,4] array.map! (number_squared) => [1, 4, 9, 16]

Houd er rekening mee dat we de. Niet langer gebruiken opbrengst trefwoord; in plaats daarvan gebruiken we direct de telefoontje methode op het Proc-object, waarbij deze de waarde uit de array doorgeeft. We ontvangen hetzelfde resultaat als voorheen, maar we slaan ons blok op in een variabele om een ​​later tijdstip opnieuw te gebruiken.


lambda

Lambda-functie is bijna identiek aan Procs maar met twee belangrijke verschillen. Eerst controleert een lambda het aantal argumenten dat het ontvangt en geeft een ArgumentError als ze niet overeenkomen. Bijvoorbeeld:

l = lambda "Ik ben een lambda" l.call => "Ik ben een lambda" l.call ('arg') ArgumentError: verkeerd aantal argumenten (1 voor 0)

Ten tweede verschaffen lambda's verkleinwoordrendementen - wat betekent dat wanneer een Proc in zijn uitvoering een return statement tegenkomt, het de methode stopt en de geleverde waarde retourneert. Lambdas daarentegen, geven hun waarde terug aan de methode, waardoor deze kan doorgaan:

def proc_math Proc.new return 1 + 1 .call return 2 + 2 end def lambda_math lambda return 1 + 1. call return 2 + 2 end proc_math # => 2 lambda_math # => 4

Zoals je kunt zien proc_math raakt de return-instructie aan binnen de Proc en retourneert de waarde van 2. In tegenstelling tot, lambda_math slaat de return-opdracht over en evalueert in plaats daarvan 2 + 2.

Een laatste opmerking: Ruby 1.9 introduceert de nieuwe "stabby" lambda-syntaxis (weergegeven met ->), die functioneel identiek is aan de traditionele lambda-syntaxis, maar de "stabby" -syntaxis is veel schoner.


Conclusie

In deze studiegids hebben we de belangrijkste verschillen tussen Blokken, Procs en Lambda's behandeld:

  • Blokken zijn voor eenmalig gebruik.
  • Procs bestaan ​​als objecten.
  • Lambdas hebben strikte argumentcontrole.

Voor een meer diepgaande beoordeling raad ik de volgende bronnen aan:

  • Rails Studiegidsen hier op Nettuts+
  • Ruby Proc-documentatie
  • Ruby programmeren 1.9
  • Metaprogrammering Ruby: Program Like the Ruby Pros