V jazyku Ruby sa metaprogramovanie stalo štandardným spôsobom písania aplikácií a existuje množstvo techník, ktoré sa dajú použiť, ale existuje len málo materiálov. V tomto príspevku sa pokúsim dať dohromady aspoň základné spôsoby, ktoré sa v Ruby dajú použiť.
V prvom rade je na mieste otázka What the f*** is metaprogramming..? odpoveď nie je jednoznačná. Dalo by sa povedať, že ide o vytváranie programov, ktoré vytvárajú alebo modifikujú iné programy... Toľko definícia podľa wikipédie, poďme sa pozrieť ako to vyzerá v praxi.
Eval a spol.
Najjednoduchším príkladom metaprogramovania môže byť napríklad metóda eval, ktorej úlohou je interpretovať zadaný reťazec ako zdrojový text Ruby.
eval "puts 'Hello world'"
Príkazov typu eval existuje v ruby viacero, jednak je to samotná metóda eval, ďalej metódy instance_eval, class_eval a module_eval, ktoré slúžia na vyhodnocovanie reťazcov v rámci danej inštancie, triedy alebo modulu a môžu byť určené napríklad na dynamické pridávanie metód. Príklad:
class Traveler def self.make_jurney where class_eval "def travel_to_#{where}; puts 'I travel to #{where}; end" end end
Potom po zavolaní statickej metódy make_jurney sa vytvorí metóda travel_to_*miesto*:
Traveler.make_jurney "Paris" t=Traveler.new t.travel_to_Paris => I travel to Paris
Určite si viete predstaviť ako užitočné to môže byť.
Method missing
V prípade, že sa rozhodnete zavolať metódu, ktorá neexistuje, sa zavolá metóda method_missing(name, *args), ktorú si môžeme (rovnako ako všetko v Ruby) prispôsobiť. Napríklad takto:
class Employee def method_missing(method, *args) assign_work(method) end def assign_work what puts "Okay boss, I will "+what end end
Potom môžeme nášmu zamestnancovi dávať rôzne príkazy a on nás bude ochotne počúvať...
e=Employee.new e.do_a_summersault => Okay boss, I will do_some_sommersaults
Upravte si Ruby podľa vášho gusta
Ruby je otvorený jazyk. Podľa môjho názoru až príliš otvorený. Takmer všetko z jazyka Ruby sa dá zmeniť a prispôsobiť, čo je na jednej strane úžasné keď si plánujete napísať nejaký vlastný DSL, ale vo veľkých projektoch to môže spôsobovať nepríjemnosti.
Nasledujúci príklad hovorí za všetko:
module Kernel alias _puts puts def puts object _puts object.reverse end end
Zatiaľ je to fajn.. jednoducho sme nahradili metódu puts novou metódou puts, ktorá vypíše reťazce odzadu, Možno vhodné na nejaký aprílový žart (zmení to puts v celej aplikácii) horšie je však to že sa tu skrýva možný zdroj chyby - ak zavoláme puts s argumentom, ktorý nie je reverzibilný dostaneme škaredú chybu. Takáto zmena môže spôsobiť hocikde v aplikácii chybu, zvlášť závažné to je ak sa chyba prejaví len občas - to potom znamená hodiny debugovania, kým sa príde na zdroj chyby.
Táto otvorenosť je pekná na vytváranie vlastných jazykov, alebo modifikovanie Ruby. Vďaka
Proc, bloky a metódy
Ruby má aj prvky funkcionálnych jazykov, predstaviteľmi týchto je aj trieda Proc a bloky (vo funkcionálnych jazykoch nazývané closures). Proc a bloky spolu tak trochu súvisia keďže Proc je de facto "zhmotneny" blok. Teda niečo také:
def give_me_proc(&block) block end proc = give_me_proc do |arg| puts arg end
Týmto sme si vytvorili nový objekt typu Proc a ten následne môžeme zavolať:
p.call("Ahoj") => Ahoj
To ale nie je všetko, z objektov typu Proc môžeme definovať metódy v danej triede. Opäť príklad za všetky drobné
class SomeClass def create_method(name,&proc) self.class.send(:define_method,name,&proc) end end
Vytvorili sme si triedu s metódou create_method, ktorá v danej triede vytvorí inštančnú metódu so zadaným menom a funkcionalitou ako parameter proc môže slúžiť buď blok:
sc=SomeClass.new sc.create_method(:my_super_method) do |var| puts var end sc.my_super_method("some text") => some text
alebo objekt typu Proc:
proc=lambda { puts "CHUNKY BACON!" } sc.create_method(:what_do_you_want_to_eat?,&proc) sc.what_do_you_want_to_eat? => CHUNKY BACON!
Dúfam že som vás veľmi neunavil. Nadnes teda koniec. Toto samozrejme nie je úplný zoznam všetkých možností. Pokračovanie je už na ceste takže sa máte načo tešiť.

0 comments ↓
There are no comments yet...Kick things off by filling out the form below.
Leave a Comment