Ruby on Rails díl.16, Ruby - Metody III.

Napsal (») 17. 3. 2007 v kategorii Programování, přečteno: 1897×
obrazky/rubyonrailsn.pngIdeální webhosting pro Ruby on Rails je banan.cz.

Jak porozumět blokům, Procesům a metodám


Úvod

Ruby poskytuje programátorovi sadou velmi silných nástrojů propůjčených z domény funkčně orientovaného programování, jmenovitě uzavření, funkce vyššího řádu a prvotřídní funkce [1]. Tyto rysy jsou implementované v Ruby přes kód bloků, Proc objektů a metod (které jsou také objekty) - koncepty které jsou blízce příbuzné se ještě liší se v subtilních cestách. Ve skutečnosti jsem zjistil, že jsem docela zmatený tímto tématem, má potíž byla v tom, abych porozuměl rozdílu mezi bloky, procesy a metodami a jejich nejlepší použití v praxi.

V tomto článku jsem zformuloval moje porozumění tohoto aspektu Ruby, které jde následkem rozsáhlého studia Ruby knih, dokumentace a komp.jaz.ruby.

Procesy

Po nekonečném hledáné v Ruby dokumentaci, Procesy jsou definovány tímto způsobem: Proces objekty jsou bloky kódu který byl vázaný na sadu lokálních proměnných. Kód může být přivolaný v různých souvislosti a ještě zpřístupní dané proměnné.

A užitečný příklad je:

def gen_times(faktor)
return Proc.new {|n| n*faktor }
end

times3 = gen_times(3) # 'faktor' je nahrazen 3
times5 = gen_times(5)

times3.call(12) #=> 36
times5.call(5) #=> 25
times3.call(times5.call(4)) #=> 60


Proces hraje v Ruby roli funkcí. Přesnější je nazývat je objekty funkce, stejně jako všechno v Ruby jsou také objekty. Takové objekty mají jméno ve folkloru - funktoru. Funktor je definovaný jako objekt, který je volán nebo nazván jako kdyby to bylo obyčejná funkce, obvykle se stejnou syntaxí, to je přesně to, co znamená Proces.

Z příkladu a definice nahoře, je zřejmé že Ruby Proces může také sloužit jako uzavření. Na Wikipedia,je uzavření definované jako funkce, která se odkazuje na nezávisle proměnné v jejich podobě zápisu. Všimněte si jak těsně jsou zmapovány v Rubyově definičním bloku kódu který byl vázaný na sadu lokální proměnných.

Více na Procesech

Proces v Ruby je prvotřídní objekt, mohou být vytvořeny během runtime, uloženy v datových strukturách, předány jako argumenty dalším funkcím a vrácené jako hodnoty dalších funkcí. Ve skutečnosti, gen_times příklad demonstruje tyto všechny kritéria, s výjimkou "předání argumentů dalším funkcím". Toto může být realizováno tímto způsobem:

def foo (a, b)
a.call(b)
end

putser = Proc.new {|x| puts x}
foo(putser, 34)


Tady je také těsnopisný zápis pro vytvoření Procesu - Kernel metoda lambda [2] (probereme si podrobněji metody již brzy, ale pro tento krát budeme předpokládat, že Kernel metoda je něco příbuzného s globální funkcí, která může být volána odkudkoli z kódu). S použitím lambda Procesu předchozí příklad může být přepsán takto:

putser = lambda {|x| puts x}


Rozdíly mezi lambda a Proc.new

Ve skutečnosti jsou dva nepatrné rozdíly mezi lambda a Proc.new. První, argument který se kontroluje. Ruby dokumentace pro lambda říká:Rovnocenná s Proc.new, s výjimkou kontrolou výsledných Proc objektů počtem parametrů prošlých když ja volána.. Pro lepší představu se to dá demonstrovat takto:

lamb = lambda {|x, y| puts x + y}
pnew = Proc.new {|x, y| puts x + y}

# funguje dobre, tiskne 6
pnew.call(2, 4, 11)

# vyhodi nam to error hlasku
lamb.call(2, 4, 11)



Druhý, je rozdíl ve způsobu, jak josu ovládané návraty z Procesů. A návrat z Proc.new návraty z ohraničující metody (chovajíci se právě jako návrat z bloku, více na toto téma později):

def try_ret_procnew
ret = Proc.new { return "Baaaf" }
ret.call
"Toto neni definovano"
end

# vytiskne "Baaaf"
puts try_ret_procnew


Zatímco návrat z lambda jedná více konvenčně, vracejíc se ke své metodě call:

def try_ret_lambda
ret = lambda { return "Baaaf" }
ret.call
"Toto se tiskne"
end

# vytiskne "Toto se tiskne"
puts try_ret_lambda


S tomto světle, bych osobně doporučoval používání lambda namísto Proc.new, jestliže není pozdější chování striktně požadované.

Ruby lambda je neobvyklá v tom že volba jmen parametru ovlivní další chování:

x = 3
lambda{|x| "x stale odkazuje na vnejsi promennou"}.call(4)
puts x # x je nyni 4, ne 3
Štítky: Ruby on Rails
Facebook Twitter Topčlánky.cz Linkuj.cz

Komentáře

Článek ještě nebyl okomentován.


Nový komentář

Téma:
Jméno:
Notif. e-mail *:
Komentář:
  [b] [obr]
Odpovězte prosím číslicemi: Součet čísel jedenáct a deset