# Metaprogramming

**URL:** <https://www.ruby-forum.com/t/metaprogramming/217613>\
**Category:** IT\
**Created:** [March 6, 2012, 6:30pm UTC](https://www.ruby-forum.com/t/metaprogramming/217613 "2012-03-06T18:30:21Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![luislavena](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/0ea827/32.png) [@luislavena](https://www.ruby-forum.com/u/luislavena)\
**Post date:** [March 6, 2012, 6:30pm UTC](https://www.ruby-forum.com/t/metaprogramming/217613/1 "2012-03-06T18:30:21Z")

</div>

Volevo approfondire qualche nozione base di ruby prima di iniziare un  
nuovo progetto con tema DSL. Ruby è sicuramente di grande aiuto ma  
alcune cose non me le spiego o devo capirle meglio:

Questione 1.

Mi chiedevo il motivo per cui instance\_eval e class\_eval agiscono al  
contrario:

class Test; end  
actions = %w(say think make)  
actions.each do |action|  
Test.instance\_eval “def #{action}; "What do i have to #{action}?";  
end”  
end  
Test.say

viceversa class\_eval ha effetto solo sull’istanza ma li confondo sempre

Spesso la sintassi ruby offre diversi modi per fare la stessa cosa ma a  
volte mi chiedo se ci possono essere anche piccole differenze:

Questione 2.

Differenza tra send e **send**  
A parte il warning del secondo mi sembrano uguali

class Test; end  
actions = %w(say think make send **send** )  
actions.each do |action|  
Test.instance\_eval “def #{action}; "What do i have to #{action}?";  
end”  
end  
(eval):1: warning: redefining ` **send** ’ may cause serious problems  
=\> [“say”, “think”, “make”, “send”, “ **send** ”]

irb(main):008:0\> Test.singleton\_methods  
=\> [:say, :think, :make, :send, : **send**]

Questione 3.

Mi chiedevo la differenza tra il definire i metodi nella metaclass o  
intrinseci alla classe (self):

#metaclass  
class Test  
class \<\< self  
def name  
“Ambrogio”  
end  
name  
end  
end  
Test.class

#self  
class Test  
def self.name  
“Ambrogio”  
end  
name  
end  
Test.class

> **[Metaprogramming in Ruby: It's All About the Self](https://yehudakatz.com/2009/11/15/metaprogramming-in-ruby-its-all-about-the-self/)**
>
> After writing my last post on Rails plugin idioms, I realized that Ruby
> metaprogramming, at its core, is actually quite simple.
> 
> It comes down to the fact that all Ruby code is executed code--there is no
> separate compile or runtime phase. In Ruby,...

Questione 4.

Differenza tra yield e &block.  
Questa è più sui concetti base che sulla metaprogrammazione ma sono  
curioso di sapere qualche opinione.

> <https://gist.github.com/marcomd/1987631>

#yield  
class A  
def go(\*attrs)  
p “Before block”  
attrs.each do |attr|  
p yield(attr)  
end if block\_given?  
p “After block”  
end  
end  
a=A.new  
a.go “1”,“2” do |i|  
“ciao#{i}”  
end

#&block  
class B  
def go(\*attrs, &block)  
p “Before block”  
attrs.each do |attr|  
p block.call(attr)  
end if block\_given?  
p “After block”  
end  
end  
b=B.new  
b.go “1”,“2” do |i|  
“ciao#{i}”  
end

#alternativa con accesso diretto  
class C  
attr\_reader :attr  
def initialize  
@attr = “”  
end  
def go(\*attrs, &block)  
p “Before block”  
attrs.each do |attr|  
@attr = attr  
p instance\_eval(&block)  
end if block\_given?  
p “After block”  
C.name  
end  
end  
c=C.new  
c.go “1”,“2” do  
“ciao#{attr}”  
end

---

<div class="post-metadata">

**Author:** ![triplem](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/b19c9b/32.png) [@triplem](https://www.ruby-forum.com/u/triplem)\
**Post date:** [March 6, 2012, 6:49pm UTC](https://www.ruby-forum.com/t/metaprogramming/217613/2 "2012-03-06T18:49:31Z")

</div>

On Mar 6, 2012, at 6:30 PM, Marco M. wrote:

> Volevo approfondire qualche nozione base di ruby prima di iniziare un  
> nuovo progetto con tema DSL. Ruby sicuramente di grande aiuto ma  
> alcune cose non me le spiego o devo capirle meglio:
> 
> Questione 1.
> 
> Mi chiedevo il motivo per cui instance\_eval e class\_eval agiscono al  
> contrario:

Non agiscono al contrario, anche se in effetti il wording e’ francamente  
molto discutibile.  
instance\_eval agisce nel contesto in cui Test e’ una istanza di Class,  
mentre class\_eval agisce nel contesto della classe - cioe’ come una  
istanza.  
Tricky a dir poco.

> Questione 2.
> 
> Differenza tra send e **send**  
> A parte il warning del secondo mi sembrano uguali

AFAIK molte classi sovrascrivono send. Dove sovrascrivere e’ inteso come  
overwrite. Sono in condizioni pietose, penso in inglese ma con un  
inglese di merda, quindi magari sbaglio qualche termine in italiano.

> Questione 3.
> 
> Mi chiedevo la differenza tra il definire i metodi nella metaclass o  
> intrinseci alla classe (self):

AFAIK nessuna, solo syntax sugar. Ma non sono stupito se qualcuno mi  
corregge.

> Questione 4.
> 
> Differenza tra yield e &block.  
> Questa pi sui concetti base che sulla metaprogrammazione ma sono  
> curioso di sapere qualche opinione.
> 
> [Example 4 · GitHub](https://gist.github.com/1987631)

E’ tutto documentato qui:  
[http://innig.net/software/ruby/closures-in-ruby](http://innig.net/software/ruby/closures-in-ruby)  
&block lo puoi salvare in una variabile e ci sono differenze nell’error  
handling piu’ che altro.

ngw

p.s. Ma com’e’ che comp.lang.ruby sembra semimorto?

---

<div class="post-metadata">

**Author:** ![triplem](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/b19c9b/32.png) [@triplem](https://www.ruby-forum.com/u/triplem)\
**Post date:** [March 7, 2012, 11:46am UTC](https://www.ruby-forum.com/t/metaprogramming/217613/3 "2012-03-07T11:46:41Z")

</div>

On Mar 6, 2012, at 6:49 PM, Nicholas W. wrote:

> > Mi chiedevo il motivo per cui instance\_eval e class\_eval agiscono al  
> > contrario:
> 
> Non agiscono al contrario, anche se in effetti il wording e’ francamente molto  
> discutibile.  
> instance\_eval agisce nel contesto in cui Test e’ una istanza di Class, mentre  
> class\_eval agisce nel contesto della classe - cioe’ come una istanza.  
> Tricky a dir poco.

instance\_eval modifica il self mentre class\_eval modifica sia il self  
sia il current\_class. Usando class\_eval puoi per esempio riaprire una  
class basandoti su una variabile che rappresenta la classe.  
Es:

module MyModule

def self.included base  
base.class\_eval do

# qui stai riaprendo la classe base

```
    # class_eval modifica il current_class mentre il blocco viene 

```

eseguito  
end  
end

end

> > Mi chiedevo la differenza tra il definire i metodi nella metaclass o  
> > [Example 4 · GitHub](https://gist.github.com/1987631)  
> > [http://lists.ruby-it.org/mailman/listinfo/ml](http://lists.ruby-it.org/mailman/listinfo/ml)  
> > Andrea C.  
> > [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![triplem](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/b19c9b/32.png) [@triplem](https://www.ruby-forum.com/u/triplem)\
**Post date:** [March 7, 2012, 12:59pm UTC](https://www.ruby-forum.com/t/metaprogramming/217613/4 "2012-03-07T12:59:28Z")

</div>

Grazie Andrea per lo spunto, guarda questi esempi:

class Test; end  
Test.class\_eval {def say; “hello”; end}  
Test.say  
#NoMethodError: undefined method `say’ for Test:Class  
Test.new.say  
#=\> “hello”

class Test; end  
Test.instance\_eval {def say; “hello”; end}  
Test.say  
#=\> “hello”  
Test.new.say  
#NoMethodError: undefined method `say’ for #Test:0x2cafb88

Questo il motivo per cui genera un pò di confusione.

Ho elaborato il tuo esempio:

class Test  
def included  
self.class.class\_eval do  
# riapro la classe base  
yield  
end  
end  
end  
Test.class\_eval {def say; “hello”; end}  
Test.say  
#NoMethodError: undefined method `say’ for Test:Class

test=Test.new  
test.say  
#=\> “hello”

#Aggiungo alla classe base col tuo spunto  
test.included {def say; “hello”; end}  
Test.say  
#=\> “hello”  
Test.new.say  
#=\> “hello”

Così ci siamo ma è stato necessario il metodo included

---

<div class="post-metadata">

**Author:** ![triplem](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/b19c9b/32.png) [@triplem](https://www.ruby-forum.com/u/triplem)\
**Post date:** [March 7, 2012, 5:39pm UTC](https://www.ruby-forum.com/t/metaprogramming/217613/5 "2012-03-07T17:39:47Z")

</div>

On Mar 7, 2012, at 12:59 PM, Marco M. wrote:

> Grazie Andrea per lo spunto, guarda questi esempi:
> 
> class Test; end  
> Test.class\_eval {def say; “hello”; end}  
> Test.say  
> #NoMethodError: undefined method `say’ for Test:Class  
> Test.new.say  
> #=\> “hello”

Qui aggiungi un metodo di instanza on di classe.  
Se vuoi aggiungere un metodo di istanza lo devi aggiungere alla classe  
quando viene riaperta e quindi al self.

class Test; end  
Test.class\_eval do  
class \<\< self  
def say  
“hi”  
end  
end  
end  
Test.say

> Ho elaborato il tuo esempio:  
> Test.say  
> Test.new.say  
> #=\> “hello”
> 
> Cos ci siamo ma stato necessario il metodo included
> 
> –  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).
> 
> * * *
> 
> Ml mailing list  
> [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
> [http://lists.ruby-it.org/mailman/listinfo/ml](http://lists.ruby-it.org/mailman/listinfo/ml)

Andrea C.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![triplem](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/b19c9b/32.png) [@triplem](https://www.ruby-forum.com/u/triplem)\
**Post date:** [March 7, 2012, 2:33pm UTC](https://www.ruby-forum.com/t/metaprogramming/217613/6 "2012-03-07T14:33:14Z")

</div>

Grazie Nicholas per l’intervento e per quel link che è finito nei  
preferiti. Sono argomenti che purtroppo uso poco e dimentico in fretta.  
Ad esempio questo è un appunto che ho scritto nel 2009:  
[http://marco.mastrodonato.info/2009/06/distruttori-di-classe-in-ruby.html](http://marco.mastrodonato.info/2009/06/distruttori-di-classe-in-ruby.html)

e neanche mi ricordavo di aver mai approfondito qualcosa di così  
tecnico, in genere per lavoro riesco ad occuparmi solo della parte  
funzionale.

Comunque ruby è fenomenale, con un pò di creatività non si hanno limiti
