<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Ruby Vault &#187; Metaprogramação</title>
	<atom:link href="http://www.tbueno.com/blog/category/metaprogramacao/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.tbueno.com/blog</link>
	<description>Explorando o maravilhoso mundo de Ruby</description>
	<lastBuildDate>Tue, 24 Aug 2010 03:02:44 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Entendendo como funcionam class_eval, module_eval e instance_eval</title>
		<link>http://www.tbueno.com/blog/metaprogramacao/2009/02/entendendo-class_eval-module_eval-e-instance_eval/</link>
		<comments>http://www.tbueno.com/blog/metaprogramacao/2009/02/entendendo-class_eval-module_eval-e-instance_eval/#comments</comments>
		<pubDate>Thu, 26 Feb 2009 21:24:53 +0000</pubDate>
		<dc:creator>bueno</dc:creator>
				<category><![CDATA[Metaprogramação]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.tbueno.com/blog/?p=77</guid>
		<description><![CDATA[Para quem como eu, vem de linguagens não-dinâmicas, o que mais impressiona (e dificulta no início) é a capacidade de Ruby em se moldar e executar códigos dinamicamente. E seguindo a nossa saga pelos conceitos de metaprogramação, vamos explorar um pouco mais um recurso interessantíssimo de Ruby chamado eval. Ruby Eval O nome eval tem [...]]]></description>
			<content:encoded><![CDATA[<p>Para quem como eu, vem de linguagens não-dinâmicas, o que mais impressiona (e dificulta no início) é a capacidade de Ruby em se moldar e executar códigos dinamicamente. E seguindo a nossa saga pelos <a title="conceitos de metaprogramação" href="http://www.tbueno.com/blog/metaprogramacao/2009/02/tudo-que-voce-sempre-quis-saber-sobre-metaprogramacao/">conceitos de metaprogramação</a>, vamos explorar um pouco mais um recurso interessantíssimo de Ruby chamado <strong>eval</strong>.</p>
<h2>Ruby Eval</h2>
<p>O nome eval tem origem na palavra inglesa evaluation, que em uma tradução livre significa &#8220;avaliar o valor de algo&#8221;, no caso de Ruby, o valor de uma expressão ou trecho de código.</p>
<p>No caso de Ruby, a melhor definição seria &#8220;interpretar&#8221;, devido ao fato que além de avaliar, o código recebido também é executado, como no exemplo abaixo:</p>
<pre class="brush: ruby">eval("puts 'Hello World'") # =&gt; Hello World</pre>
<p>No post anterior sobre <a href="http://www.tbueno.com/blog/metaprogramacao/2009/02/tudo-que-voce-sempre-quis-saber-sobre-metaprogramacao/">metaprogramação</a>, eu utilizei o método <strong>instance_variable_set</strong> da classe Object.</p>
<p>Esse método pode ser utilizado para evitar repetições de código. No código abaixo eu mostro como é a implementação desse método e como ele é usado na prática:</p>
<p><strong>Implementação redundante de um construtor de uma classe</strong>:</p>
<pre class="brush: ruby">
class CalendarEvent
  def initialize(start_time=0, end_time=0, attendees=0)
    @start_time = start_time
    @end_time = end_time
    @attendees = attendees
  end
end
</pre>
<p><strong>Implementação melhorada com o uso de eval</strong>:</p>
<pre class="brush: ruby">
#Primeiro, adicionamos o seguinte código à classe Object,
#para torná-lo disponível para as instâncias de quaisquer classe
class Object
  private
  def set_instance_variables(binding, *variables)
    variables.each do |var|
      instance_variable_set("@#{var}", eval(var, binding))
   end
  end
end

#Depois podemos melhorar a nossa classe

class CalendarEvent
  def initialize(start_time=0, end_time=0, attendees=0)
    set_instance_variables(binding, *local_variables)
  end
end

c = CalendarEvent.new(4,5,2)

puts c.instance_eval "@start_time"   # =&gt; 4
</pre>
<p><span id="more-77"></span></p>
<p>Em Ruby, temos mais alguns métodos do tipo eval disponível:</p>
<p>* instance_eval<br />
* class_eval<br />
* module_eval</p>
<p>Dentre esses, a diferença básica está no escopo aonde os métodos serão executados: em classes ou instâncias.</p>
<h2>Module.class_eval</h2>
<p>O método da classe Module, chamado class_eval, nos possibilita executar blocos dentro do escopo de uma classe. Uma possibilidade útil criada por esse método é a de criar dinamicamente métodos a uma classe, como no exemplo do attr_accessor, que é implementado em C, mas se fosse implementado em Ruby seria algo do tipo:</p>
<pre class="brush: ruby">
class Class
  def attr_acc(*vars)
    return if vars.empty?
    code = ""
    vars.each do |v|
      # Cria gets para as variaveis
      code &lt;&lt; "def #{v}; @#{v}; end;"
      # Cria sets para as variaveis
      code &lt;&lt; "def #{v}=(value); @#{v} = value; end;"
    end
    self.class_eval code

  end
end

#podemos criar uma classe que utiliza nossa cópia do attr_acc
class Foo
attr_acc :bar
end

#... e testar pra ver se ela funciona
f = Foo.new
f.bar = "hello"
puts f.bar                  # =&gt; hello
</pre>
<h2>Module.module_eval</h2>
<p>Na verdade, podemos realizar algo parecido com o exemplo anterior com uma sintaxe levemente diferente usando Mocule.module_eval como no exemplo abaixo, aonde eu crio um método que retorna os 5 primeiro múltiplos de 3:</p>
<pre class="brush: ruby">
Fixnum.module_eval do
  def self.multiple_of_three
     [3,6,9,12,15]
  end
end
puts  Fixnum.multiple_of_three
#=&gt; 3
6
9
12
15
</pre>
<p>É importante ressaltar que no exemplo acima, estamos criando dinamicamente um método na classe Fixnum, e não um método para as instâncias dessa classe, de modo que a chamada abaixo acabará nos retornando uma exceção:</p>
<pre class="brush: ruby">
5.multiple_of_three   # =&gt;NoMethodError: undefined method `multiple_of_three' for 5:Fixnum
</pre>
<h2>Object.instance_eval</h2>
<p>O método intance_eval, da classe Object, por sua vez implementa a função eval sob o escopo de instâncias.</p>
<pre class="brush: ruby">
class Foo
  def initialize
    @bar = 'hey'
  end
  def change_bar
    @bar = "ho!"
  end
end

foo = Foo.new
puts foo.instance_eval "@bar"
foo.change_bar
puts foo.instance_eval "@bar"
</pre>
<h2>Conclusão</h2>
<p>Metaprogramação acaba ficando mais claro na medida que começamos a compreender o verdadeiro poder oferecido pela linguagem. Uma ótima fonte de inspiração e estudo é o código de projetos largamente utilizados em Ruby.</p>
<p>É com recursos como esse que o Rails (e outras ferramentas escritas em Ruby) adicionam diversas funcionalidades ao core de Ruby para comtemplar suas &#8220;mágicas&#8221;.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tbueno.com/blog/metaprogramacao/2009/02/entendendo-class_eval-module_eval-e-instance_eval/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tudo que você sempre quis saber sobre Metaprogramação mas tinha vergonha de perguntar</title>
		<link>http://www.tbueno.com/blog/metaprogramacao/2009/02/tudo-que-voce-sempre-quis-saber-sobre-metaprogramacao/</link>
		<comments>http://www.tbueno.com/blog/metaprogramacao/2009/02/tudo-que-voce-sempre-quis-saber-sobre-metaprogramacao/#comments</comments>
		<pubDate>Fri, 13 Feb 2009 20:15:37 +0000</pubDate>
		<dc:creator>bueno</dc:creator>
				<category><![CDATA[Metaprogramação]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[singleton]]></category>

		<guid isPermaLink="false">http://www.tbueno.com/blog/?p=25</guid>
		<description><![CDATA[A arte de escrever programas que escrevem programas está presente desde o início da ciência da computação, com o objetivo de aumentar a produtividade diminuindo a quantidade de código a ser escrito. O prefixo grego meta está presente na nossa língua, tornando mais fácil o entendimento do conceito por nós brasileiros logo de cara, bastando [...]]]></description>
			<content:encoded><![CDATA[<p>A arte de escrever <strong>programas que escrevem programas</strong> está presente desde o início da ciência da computação, com o objetivo de aumentar a produtividade diminuindo a quantidade de código a ser escrito. O prefixo grego <strong>meta</strong> está presente na nossa língua, tornando mais fácil o entendimento do conceito por nós brasileiros logo de cara, bastando apenas lembrar das aulas de literatura ou dos livros de Machado de Assis.</p>
<div id="attachment_28" class="wp-caption aligncenter" style="width: 346px"><img src="http://www.tbueno.com/blog/wp-content/uploads/2009/02/machassis.jpg" alt="Machadão, o rei da Metaliteratura" title="machassis" width="336" height="390" class="size-full wp-image-28" /><p class="wp-caption-text">Machadão, o rei da Metaliteratura</p></div>
<h2>Metaclasses</h2>
<p>Lembra daquela frase que dizia que &#8220;em Ruby tu é objeto&#8221;? Pois é, vamos olhar o seguinte código:</p>
<pre class="brush: ruby">
class Zombie
  def self.alive
    puts "i am alive"
  end
end

Zombie.class     # => Class
Zombie.alive      # => "i am alive"
z = Zombie.new
z.class              # => Zombie
</pre>
<p><span id="more-25"></span></p>
<p>Quando definimos uma classe (no caso a Zombie), uma constante (que em Ruby são escritas com a primeira letra em maiúsculo, lembram?) é criada com o mesmo nome para armazenar um objeto do tipo Class. Assim, quando chamamos um método dessa &#8220;constante&#8221;, essa mensagem é passada para um objeto Class que o representa.</p>
<p>É interessante frisar que <strong>objetos não armazenam métodos, apenas classes fazem isso</strong>. Então quando invocamos um método de Zombie, na verdade, este método está armazenado em um objeto do tipo Class.</p>
<p>Vamos brincar mais um pouco:</p>
<pre class="brush: ruby">
Zombie.to_s      #=> "Zombie"
</pre>
<p>Ué? De onde esse método saiu se não o definimos? </p>
<p>O que ocorre aqui é que aquele objeto mencionado anteriormente, que representaria uma classe Zombie, recebe no momento de sua criação todos os métodos com o sufixo &#8220;self&#8221; ( que representam os métodos de classe) e herda todos os métodos da classe <strong>Class</strong>. Nesse exemplo,<strong> to_s</strong> é um método da classe Class. Na verdade, a definição de Zombie é uma classe virtual criada dinamicamente para armazenar os métodos da classe. Esses objetos de classe são chamados de <strong>Metaclasses</strong>.</p>
<p>Resumindo: Uma classe também é  um objeto, mas de um tipo bem particular! Mais precisamente, um objeto da classe <strong>Class</strong>.</p>
<h2>Metaprogramação em Ação</h2>
<p>Vamoz continuar brincando com a nossa classe Zombie. É possível que criemos variáveis em tempo de execução dentro de apenas uma instância:</p>
<pre class="brush: ruby">
z = Zombie.new
z.instance_variable_set("@eyes", 3)
z.eyes                         # =>NoMethodError: undefined method `eyes' for #<Zombie:0xb7d8c39c @eyes=3>
</pre>
<p>Opa, será que não funcionou o nosso exemplo? Na verdade, sim. Só que não possuímos nenhum método de acesso à propriedade @eyes. Podemos garantir isso, através do seguinte método:</p>
<pre class="brush: ruby">
z.instance_variables        # =>  ["@eyes"]
</pre>
<p>Mas como faríamos para acessar a propriedade @eyes de nosso zumbi? Isso nos leva ao próximo tópico:</p>
<h2>Classes Singleton</h2>
<p>Primeiramente, esqueça completamente o Design Pattern Singleton . As classes Singleton de Ruby só compartilham o nome com este padrão. Singleton class pode ser resumida como uma classe virtual, aonde um objeto de uma classe já definida pode assumir um comportamento particular, diferente de outros objetos da mesma classe. Vejamos abaixo:</p>
<pre class="brush: ruby">
def z.eyes
  "I have #{@eyes} eyes"
end

z.eyes   #  => "I have 3 eyes"
</pre>
<p>Nesse exemplo nós estamos criando um método apenas para a instância(objeto) &#8220;z&#8221; da classe Zombie. Agora nosso objeto &#8220;z&#8221; é um classe Singleton, única, com um comportamento próprio. Podemos perguntar para um objeto se ele possui métodos singleton:</p>
<pre class="brush: ruby">
z.singleton_methods             #=> ["eyes"]
</pre>
<p>Certo, vamos pirar mais um pouco na batatinha. Observe este exemplo:</p>
<pre class="brush: ruby">
y = Zombie.new

class << y
  def brains_eaten
    "millions"
  end
end

y.singleton_methods        # => ["brains_eaten"]
y.brains_eaten                 #=> "millions"
</pre>
<p>Essa sintaxe até certo ponto estranha para iniciantes é o jeito Ruby de dizer que você está &#8220;abrindo&#8221; uma classe singleton do objeto y . Mas as coisas interessantes não param por aí. Podemos fazer Singletons de instâncias de classes como no exemplo a seguir:</p>
<pre class="brush: ruby">
class Fixnum
  class << self
    def desc
     puts "another description"
    end
  end
end

Fixnum.desc        # => another description
</pre>
<p>Ou, para ficar mais familiar, podemos repetir o mesmo exemplo desta maneira, que é bem comum quando manipulamos objetos do ActiveRecord:</p>
<pre class="brush: ruby">
class Fixnum
  def self.description
    puts "i am a number"
  end
end

Fixnum.description         # => i am a number
</pre>
<p>O que fizemos foi simplesmente adicionar um método dinamicamente usando linguagem de programação, ou seja Metapgrogramação.</p>
<p>Por último, ficaremos com um idioma clássico do Ruby, que está presente em qualquer brincadeira que se presente de metaprogramação:</p>
<pre class="brush: ruby">
class << self; self; end
</pre>
<p>Esta pequena e bizarra linha, nos retornará uma classe singleton da classe que a utilizar, como demonstrado no exemplo abaixo:</p>
<pre class="brush: ruby">
class Screamer

  self.module_eval do
    define_method :scream do
      puts "I am a instance method!! AAAAAAH"
    end
  end

  (class << self; self; end).module_eval do
    define_method :scream do
      puts "I am a class method! AAAAAAH"
    end
  end

end

Screamer.scream         # => I am a class method! AAAAAAH
Screamer.new.scream     #I am a instance method!! AAAAAAH
</pre>
<p>Por enquanto é só. No futuro retomarei esse assunto com exemplos melhores para tornar tudo mais claro na prática.</p>
<p>Referências e links para se aprofundar no assunto:</p>
<p><a href="http://ola-bini.blogspot.com/2006/09/ruby-metaprogramming-techniques.html">Ruby Metaprogramming techniques</a> por Ola Bini</p>
<p><a href="http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html">Seeing Metaclasses Clearly</a> por Whytheluckystiff</p>
<p><a href="http://pmade.com/articles/2008/ruby-singleton">Understanding Ruby Singleton Classes</a> por Peter Jones.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.tbueno.com/blog/metaprogramacao/2009/02/tudo-que-voce-sempre-quis-saber-sobre-metaprogramacao/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
