[转]eval, class_eval, instance_eval和binding
http://www.cnblogs.com/rubylouvre/archive/2011/08/28/2112321.html
前些天写html生成器的时候用到了erb,在生成html的时候是这么一句:
html=tpl.result(binding)
binding这个变量(Kernel的一个方法 T_T)有点古怪,就搜了下。它表示了ruby的当前作用域,没有任何对外可见的成员函数,唯一的用途就是传递给eval作第二个参数。因而可以这样:
def test_binding magic='brother Chun is PURE MAN' return bindingendeval "puts magic", test_binding
a=Baby.new { name "Makr" father "Mike" age 0.2}a.cry
class Baby def initialize(&blc) instance_eval(&blc) #here end def name(str=nil) @name=str if str @name end def age(num=nil) @age=num if num @age end def father(str=nil) @father=str if str @father end def cry puts "#{name} is only #{age.to_s} year old, he wanna milk! Brother Chun is PURE MAN!" endend#有重复代码?用class_eval缩短之,有点像宏了:class Baby def initialize(&blc) instance_eval(&blc) end def Baby.my_attr(*names) names.each{|n| class_eval %{ def #{n}(x=nil) @#{n}=x if x @#{n} end } } end my_attr :name, :father, :age def cry puts "#{name} is only #{age.to_s} year old, he wanna milk! Brother Chun is PURE MAN!" endend a=Baby.new { name "Makr" father "Mike" age 0.2}a.cry
class Baby def my_instance_eval(code) eval code, binding end def Baby.my_class_eval(code='') eval code, binding endend#就这么简单。调用的时候就像这样:class Baby def initialize(code) my_instance_eval(code) end my_attr :name, :father, :ageenda=Baby.new %{ name "Test" father "Orz" age 0.2}
def add_method(c, m, &b)c.instance_eval { #在此使用class_eval是一样的效果define_method(m, &b)}endadd_method(String, :greet) { "Hello, " + self }p "world".greet # => "Hello, world"