Metaprogramovanie v Ruby

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ť.

pošli na vybrali.sme.sk

0 comments ↓

There are no comments yet...Kick things off by filling out the form below.

Leave a Comment