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.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 opbrengst
zijn kracht. Het gebruik van blokken in Ruby is eindeloos, en we gebruiken ze vaak in onze code.
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-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.
In deze studiegids hebben we de belangrijkste verschillen tussen Blokken, Procs en Lambda's behandeld:
Voor een meer diepgaande beoordeling raad ik de volgende bronnen aan: