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
Questione 4.
Differenza tra yield e &block.
Questa è più sui concetti base che sulla metaprogrammazione ma sono
curioso di sapere qualche opinione.
#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