副标题: Program Like the Ruby Pros
作者: Paolo Perrotta
出版社: Pragmatic Bookshelf
出版年: 2010-2-22
页数: 240
定价: USD 32.95
装帧: Paperback
ISBN: 9781934356470
作者: Paolo Perrotta
出版社: Pragmatic Bookshelf
出版年: 2010-2-22
页数: 240
定价: USD 32.95
装帧: Paperback
ISBN: 9781934356470
内容简介 · · · · · ·
Everyone in the Ruby world seems to be talking about metaprogramming--how you can use it to remove duplication in your code and write elegant, beautiful programs. Now you can get in on the action as well.
This book describes metaprogramming as an essential component of Ruby. Once you understand the principles of Ruby, including the object model, scopes, and eigenclasses, you're... (展开全部) Everyone in the Ruby world seems to be talking about metaprogramming--how you can use it to remove duplication in your code and write elegant, beautiful programs. Now you can get in on the action as well.
This book describes metaprogramming as an essential component of Ruby. Once you understand the principles of Ruby, including the object model, scopes, and eigenclasses, you're on your way to applying metaprogramming both in your daily work and in your fun, after-hours projects.
Learning metaprogramming doesn't have to be difficult or boring. By taking you on a Monday-through-Friday workweek adventure with a pair of programmers, Paolo Perrotta helps make mastering the art of metaprogramming both straightforward and entertaining.
This book describes metaprogramming as an essential component of Ruby. Once you understand the principles of Ruby, including the object model, scopes, and eigenclasses, you're... (展开全部) Everyone in the Ruby world seems to be talking about metaprogramming--how you can use it to remove duplication in your code and write elegant, beautiful programs. Now you can get in on the action as well.
This book describes metaprogramming as an essential component of Ruby. Once you understand the principles of Ruby, including the object model, scopes, and eigenclasses, you're on your way to applying metaprogramming both in your daily work and in your fun, after-hours projects.
Learning metaprogramming doesn't have to be difficult or boring. By taking you on a Monday-through-Friday workweek adventure with a pair of programmers, Paolo Perrotta helps make mastering the art of metaprogramming both straightforward and entertaining.
作者简介 · · · · · ·
Paolo Perrotta has more than ten years of experience as a developer and writer. He worked for domains ranging from embedded to enterprise software, computer games, and web applications. These days, Paolo coaches agile teams for Yoox, a large Internet fashion shop, and teaches Java to developers throughout Europe. He lives in Bologna, Italy, with his girlfriend and a cat. He lov... (展开全部)
Paolo Perrotta has more than ten years of experience as a developer and writer. He worked for domains ranging from embedded to enterprise software, computer games, and web applications. These days, Paolo coaches agile teams for Yoox, a large Internet fashion shop, and teaches Java to developers throughout Europe. He lives in Bologna, Italy, with his girlfriend and a cat. He loves Ruby.
豆瓣成员常用的标签(共20个) · · · · · ·
Ruby(77) Programming(16) metaprogramming(8) 程序设计(6) PragmaticBookshelf(5) 计算机技术(3) Ruby红宝石(3) Script(3)
喜欢读"Metaprogramming Ruby"的人也喜欢 · · · · · ·
按有用程度 按页码先后 最新笔记
-
第209页
#chapter 8 之前的记录不了了,从这里开始继续写笔记 1.一般module使用两种办法来扩展包含他的类 a.定义方法,当包含的时候这些方法就成为了对应的类的instance method,这是module和include最直接的作用 b.定义hook_method self.included,当被包含的时候会自动执行到,这个时候可以做一些事情,比如扩展被包含类的eigenclass来扩展类方法,通过alias_method修改原来该类的一些方法的行为 2.如果从写了method_mis... (更多)#chapter 8之前的记录不了了,从这里开始继续写笔记1.一般module使用两种办法来扩展包含他的类 a.定义方法,当包含的时候这些方法就成为了对应的类的instance method,这是module和include最直接的作用 b.定义hook_method self.included,当被包含的时候会自动执行到,这个时候可以做一些事情,比如扩展被包含类的eigenclass来扩展类方法,通过alias_method修改原来该类的一些方法的行为2.如果从写了method_missing,调用private方法的时候,会调到method_missing,不写method_missing的时候是NoMethodError但是会说明是private method call笔记两个方法Array#rejectArray#combination (收起)2012-02-06 10:06:17 2回应
-
第133页
singleton method && eigenclass ##全书的重点来了## 1.class macro class M def self.deprecate(old_name,new_name) define_method(old_name) do |*args,&block| warn "xxx" send(new_mehthod,*args,&block) end end deprecate :GetTitle,:title deprecate :GetTitle,:title deprecate :GetTitle,:title ... (更多)singleton method && eigenclass##全书的重点来了##1.class macroclass M def self.deprecate(old_name,new_name) define_method(old_name) do |*args,&block| warn "xxx" send(new_mehthod,*args,&block) end end deprecate :GetTitle,:title deprecate :GetTitle,:title deprecate :GetTitle,:title end2.eigenclassclass << obj # just entered the eigenclass scope of obj,endobj = Object.newec = class << obj selfendeigenclass.class #classdef obj.s_method ;endec.instance_methods.grep /s/ # s_method##class_eval 改变当前的self和class,class为当前obj的class##instance_eval 改变当前的self和class,class为当前obj的eigenclass所以在instance_eval里面用def定义的方法是定义在其eigenclass上的instance方法所以obj才能继续使用比较一下代码o = Class.newo.instance_eval { //用def定义的方法都在当前scope的class上,instane_eval把当前的class设置为eigenclass了 def m p "m" end //self是指o,self.z也是o的eigenclass上面的方法 def self.z p "z" end 这是唯一一个def t和def self.t都是统一个方法的地方}o.m #m 改变当前的class,所以定义了当前的eigenclass的实例方法,o为其实例,可以调用o.z #z 改变当前的self,定义在self上的方法即使定义在o的eigenclass上面的方法Object.class_eval do def eigenclass class << self self end endend (收起)2012-01-17 18:29:17 2回应
-
第131页
class 关键词的等价定义 c = Class.new(Array) do #now you entered the class scope def m #instance method end end M = c #M represent the class 此时c.name会被定义成M,这是ruby内部做的处理,除了赋值以外的另外一个副作用 而且只有在c c.name #M T = c c.name #M T.name #M c.instance_eval {@name = nil} c.name #M ##so what the fuck ? (更多)class 关键词的等价定义c = Class.new(Array) do #now you entered the class scope def m #instance method endendM = c #M represent the class 此时c.name会被定义成M,这是ruby内部做的处理,除了赋值以外的另外一个副作用而且只有在cc.name #MT = cc.name #MT.name #Mc.instance_eval {@name = nil}c.name #M ##so what the fuck ? (收起)2012-01-17 18:21:43 回应
-
第1页
去年国庆期间发现了《Meta Programming Ruby 》这本书, 一口气读完,并记录了笔记,笔记记录很随意,之前并没有打算拿出来共享。也没有时间去整理, 大家多多包涵吧。有机会的话,希望能把这本书翻译出来。 Ruby元编程 1 Monday with Bill 2 Open Classes /代码内容已省略/ 虽然Ruby的类是开放的,但是类似于以上代码这种做法,值得考量! The Money Example: (更多)去年国庆期间发现了《Meta Programming Ruby 》这本书, 一口气读完,并记录了笔记,笔记记录很随意,之前并没有打算拿出来共享。也没有时间去整理, 大家多多包涵吧。有机会的话,希望能把这本书翻译出来。Ruby元编程1 Monday with Bill2 Open Classesclass String def to_alphanumeric gsub /[^\w\s]/, '' end end虽然Ruby的类是开放的,但是类似于以上代码这种做法,值得考量! The Money Example:class Numeric def to_money Money.new(self * 100) end endRuby标准库里有好多方法是打开class来添加方法的。The Problem with Open Classes: open classes的阴暗面: 可能会给类引入bug,比如重写了类已经有的同名方法。 关于Monkeypatches还有更多的方法。3 The Truth About Classes Ruby类背后的理论: What’s in a Object: 实例方法保持在对象的类里,而实例变量则由对象自己保持。这就是为什么相同类的对象共享实例方法而不共享实例变量的原因。String.instance_methods == "abc".methods # => true String.methods == "abc".methods # => false
Classes Revisited 因为一个类也是一个对象,所以一切适用于对象的也适用于类。 Classes,像其他任何对象一样也有自己的类。String.class #= > Class
像一切任何其他对象, classes也有方法, 类的方法也是它的类的实例方法。 这就意味着一个类的方法,也就是Class类的实例方法。4> Object.class => Class > Class.superclass => Module > Module.superclass => Object > Object.superclass => nil
Object. Module, Class都是Class的实例对象。 而, Class的父类是Module, Module的父类是Object. > Class.class.superclass.class => Class Class是自己的实例。 Module, Object都是Class的实例, Class的超类又是Module, Object. ???• Class继承自Object• Object的class是Class• Class的class是它自己• 其它所有自定义class都是Class的object• 其它所有自定义class都继承自Object简单的说,就是,在继承层次上,所有class都继承自Object,同时,所有class都是Class的对象,而Class又继承自 Object,因此所有class也都是Object的对象,结论:所有class既继承自Object,同时又是Object的对象。Ruby里的MetaClass: metaclass就是定义其它class的class。现在,我们已经知道:object(请注意:Ruby中的一切都是Object的对象)不能拥有方法。但有些时候你可能想让一个object拥有它自己的方法,那该如何办呢,答案就是metaclass.那么,普通的classes,以及object,都有自己的metaclass。class Object # The hidden singleton lurks behind everyone def metaclass; class << self; self; end; end def meta_eval &blk; metaclass.instance_eval &blk; end # Adds methods to a metaclass def meta_def name, &blk meta_eval { define_method name, &blk } end # Defines an instance method within a class def class_def name, &blk class_eval { define_method name, &blk } end end5 What Happens When You Call a Method? 当你调用一个方法, ruby做2件事: a, 找到这个方法。这个过程叫方法寻找。 b, 执行这个方法。要完成这一步, Ruby需要一个叫self的东东。Method LookupMySubclass.ancestors # => MySubclass, MyClass, Object, Kernel, BasicObject
不要以为 ancestors chain只包含class, 其实也包含了module。而ancestors方法,则反映出了方法寻找的路径, 而不是superclass。话说, BasicObject是Ruby1.9引入的。方法的执行: 方法的显示和隐式调用有所不同:如果你想成为Ruby的主人,那么你必须在任何时候明确的知道self代表的是哪个object。私有方法真正的意义: 你不能用一个显式的方法接收器来调用一个私有方法。换句话说, 每次你想调用私有方法,必须要用隐式self来调用。 这意思就是私有方法在2条规则下工作: 当你想调用对象外的别的方法,那么需要一个显式的调用。 私有方法仅能被隐式的self调用。总结: • An object is composed of a bunch of instance variables and a link to a class.对象只是一组实例变量 + 指向对象的链接。• The methods of an object live in the object’s class (from the point of view of the class, they’re called instance methods).一个对象的方法保存在对象的类中• The class itself is just an object of class Class. The name of the class is just a constant.一个类本身只是Class类的对象。 类名只是一个常数。• Class is a subclass of Module. A module is basically a package of methods. In addition to that, a class can also be instantiated (with new( )) or arranged in a hierarchy (through its superclass( )).Class的父类是Module. 一个module只是一个基本的方法集合。 除此之外, 一个类也可以被实例化(使用new()方法,或者 通过superclass())。• Constants are arranged in a tree similar to a file system, where the names of modules and classes play the part of directories and regular constants play the part of files.• Each class has an ancestors chain, beginning with the class itself and going up to BasicObject.每个类都有一个始祖链, 开始于它自己,结束于BasicObject(Ruby1.9).• When you call a method, Ruby goes right into the class of the receiver and then up the ancestors chain, until it either finds the method or reaches the end of the chain.当你调用一个方法的时候, Ruby会沿着接收器的类的始祖链,找到这个方法,或者是到达链的终点。• Every time a class includes a module, the module is inserted in the ancestors chain right above the class itself.每次当一个类include一个module的时候, 这个moudle会插入这个类方法链的上一层。When you call a method, the receiver takes the role of self.当你调用一个方法的时候, 接收器充当了self的角色。转载请注明出处:blackanger on http://thoughtrails.com/ • When you’re defining a module (or a class), the module takes the role of self.当你顶一个module(或者一个类)的时候, 这个module充当了self的角色。• Instance variables are always assumed to be instance variables of self.实例变量总是被指派给self的实例变量。• Any method called without an explicit receiver is assumed to be a method of self.任何不被显式调用的方法,都被指派给self。 (收起)2011-03-22 23:25:28 回应
-
第2页
Methods 1 A Duplication Problem Dynamic Methods 使用动态方法来消除重复代码。 Calling Methods Dynamically 你可以使用一个点来调用方法。 比如: obj.my_method(my_arg) 也可以使用send(:my_method, my_arg)来调用。 但是,为什么我们要用send来代替‘.’呢? 这实际上是Ruby非常酷的一点: 使用send()方法的技术被叫做 “Dynamic Dispatch”, 下面是个例子: Camping Example: Camping(http://www.ruby-camping.co... (更多)Methods1 A Duplication ProblemDynamic Methods 使用动态方法来消除重复代码。Calling Methods Dynamically 你可以使用一个点来调用方法。 比如: obj.my_method(my_arg) 也可以使用send(:my_method, my_arg)来调用。但是,为什么我们要用send来代替‘.’呢? 这实际上是Ruby非常酷的一点: 使用send()方法的技术被叫做 “Dynamic Dispatch”, 下面是个例子:Camping Example: Camping(http://www.ruby-camping.com/)是一个Ruby写的还不到4k大小的微型框架。MVC可放在同一文件中。Camping的配置文件是用YAML来写的,例如:conf.admin = ‘Bill’ conf.title = “RubyLand” conf.topic = “Ruby and More”像以上的代码, Camping只能通过读取Yaml文件来动态的调用这些方法:load configuration if anyif conf.rc and File.exists?( conf.rc ) YAML.load_file(conf.rc).each do |k, v| conf.send(“#{k}=”, v) end endThe Test::Unit Example 另一个例子,但是Test::Unit套件里用的是send的同义方法:__send__()P.S: send()方法可以调用任何方法, 意味着对象的私有方法也可以通过send被调用, 在Ruby1.9里, send方法也可以调用私有方法,但是好像是专门为了这一目的, 换句话说, 你会有一个新的方法public_send()方法来调用public方法。Defining Methods Dynamically 我们还可以定义动态方法。你可以通过Module#define_method()来动态定义方法。例如:class MyClass define_method :my_method do |my_arg| my_arg * 3 end end obj = MyClass.new obj.my_method(2) #=> 6 step 1 使用send()方法 class Computer def initialize(computer_id, data_source) @id = computer_id @data_source = data_source end def mouse component :mouse end def cpu component :cpu end def keyboard component :keyboard end def component(name) info = @data_source.send "get_#{name}_info" , @id price = @data_source.send "get_#{name}_price" , @id result = "#{name.to_s.capitalize}: #{info} ($#{price})" return "* #{result}" if price >= 100 result end endstep 动态生成方法:class Computer def initialize(computer_id, data_source) @id = computer_id @data_source = data_source end def self.define_component(name) define_method(name) { info = @data_source.send "get_#{name}_info" , @id price = @data_source.send "get_#{name}_price" , @id result = "#{name.to_s.capitalize}: #{info} ($#{price})" return "* #{result}" if price >= 100 result } end define_component :mouse define_component :cpu define_component :keyboard endStep 3 : Sprinkling the code with Introspection 使用内省机制减少代码:class Computer def initialize(computer_id, data_source) @id = computer_id @data_source = data_source data_source.methods.grep(/^get_(.*)_info$/) { Computer.define_component $1 } end def self.define_component(name) define_method(name) { info = @data_source.send "get_#{name}_info" , @id price = @data_source.send "get_#{name}_price" , @id result = "#{name.capitalize}: #{info} ($#{price})" return "* #{result}" if price >= 100 result } end end上面initialize方法内红色的一行,就是魔术发生的地方。为了理解它,你需要知道一些东东:首先, 如果你给String#grep()方法传递一个block, 这个block是匹配的正则表达式。 第二, 这个正则括号里被匹配的部分保存在一个全局变量里$1。3 method_missing() 因为Ruby是动态语言, 没有编译器,这就意味着你可以调用不存在的方法。 Kernel#method_missing()是被每个对象继承了的。Overriding method_missing() 通过重写method_missing()方法允许你调用一个并不存在的方法。Ghost Method 幽灵方法:例子:The Ruport Example 事实上Ruport里面的to_csv方法和rows_with_conuntry()都是幽灵方法:Class Table def method_missing(id, *args, &block) return as($1.to_sym,*args,&block) if id.to_s =~ /^to_(.*)/ return rows_with($1.to_sym => args[0]) if id.to_s =~ /^rows_with_(.*)/ super end当你调用rows_with_conuntry()方法的时候,实际上是调用:rows_with(:country)。 当调用to_csv()的时候, 是调用:as(:csv) 当调用的方法不是上面这2种格式的时候,就会报出NoMethod错误,这也就是super的作用。再看一个例子: The OpenStruct Example: OpenStruct是Ruby的标准库。require 'ostruct' icecream = OpenStruct.new => #<OpenStruct> > icecream.flavor = "strawberry" => "strawberry" > icecream.flavor => "strawberry"
这里的flavor属性实际上是幽灵方法:class MyOpenStruct def initialize @attributes = {} end def method_missing(name, *args) attribute = name.to_s if attribute =~ /=$/ @attributes[attribute.chop] = args[0] else @attributes[attribute] end end end > icecream = MyOpenStruct.new => #<MyOpenStruct:0x3fcf0 @attributes={}> > icecream.flavor = "vanilla" => "vanilla"p.s. attribute.chop chop方法去掉 icecream.flavor = 的等号。Dynamic Proxies 动态代理: 把一个对象的幽灵方法在另一个对象中使用,并且可能进行一些包装,称之为动态代理。再次重构Computer Class:class Computer def initialize(computer_id, data_source) @id = computer_id @data_source = data_source end def method_missing(name, *args) super if !@data_source.respond_to?("get_#{name}_info" ) info = @data_source.send("get_#{name}_info" , args[0]) price = @data_source.send("get_#{name}_price" , args[0]) result = "#{name.to_s.capitalize}: #{info} ($#{price})" return "* #{result}" if price >= 100 result end end除了method_missing , 我们还可以定义 const_missing,看例子: def Object.const_missing(name) name.to_s.downcase.gsub(/_/, ’ ’ ) end => nil > TEST => “test”5 More method_missing()when methods clash 当方法冲突的时候class Computer instance_methods.each do |m| undef_method m unless m.to_s =~ /^__|method_missing|respond_to?/ end总结: 幽灵方法的性能不是很高。 (收起)2011-03-22 23:26:29 回应
-
第3页
第三章相关, 这章的笔记除了有书本的内容,还有我自己的一些东西,未标注。 Blocks blocks是“可调用对象(callable object)”大家族中的一员。 1 how to handle hump day blocks基础回顾 scopes概述, 还有如何使用闭包 如何通过给instance_eval()来传统一个block来更多的操控scopes 如何把blocks转换为callable object, 比如Proc和lambdas Back to the Basic The current block 在一个方法内部,你可以问Ruby是否当前的调.. (更多)第三章相关, 这章的笔记除了有书本的内容,还有我自己的一些东西,未标注。Blocksblocks是“可调用对象(callable object)”大家族中的一员。1 how to handle hump day blocks基础回顾 scopes概述, 还有如何使用闭包 如何通过给instance_eval()来传统一个block来更多的操控scopes 如何把blocks转换为callable object, 比如Proc和lambdasBack to the BasicThe current block 在一个方法内部,你可以问Ruby是否当前的调用包含一个block。def a_method return yield if block_given? 'no block' end2 Quiz: Ruby # the using Keyword: 在c#里,using关键字会做一些额外的处理:RemoteConnection conn = new RemoteConnection(“some_remote_server” ); using (conn) { conn.readSomeData(); doSomeMoreStuff(); }不管花括号内的代码是否抛出异常, using关键字都会保证在代码执行以后自动调用一个dispose()方法来关闭远程链接。Ruby版本的using:def using(resource) begin yield ensure resource.dispose end end3 Ruby闭包(Closures)def my_method x = “Goodbye” yield(“cruel”) end > x = “hello” #=> “hello” > my_method{|y| “#{x}, #{y} world”} #=> “hello, cruel world”上例中, block中引用的x变量不是方法里的x变量,而是其上下文环境中的本地变量x, 我们称之为闭包。P.S 这里需要注意一下:在Ruby1.8或者更早的版本, block有个问题,就是通过给block传递参数,从而改变本地变量。这样有时候会导致bug,例子:def my_method yield(2) end > x = 1 #=> 1 my_method do |x| # ... ... todo end > x #=> 2这样,就给把本地变量x的值,由1变为了2, 所以这个地方是有问题的。 幸好, 在Ruby1.9里面已经修复了这个问题。Scope: 作用域。 Changing Scope 改变作用域例子:v1 = 1 class MyClass v2 = 2 local_variables # => [:v2] def my_method v3 = 3 local_variables end local_variables # => [:v2] end obj = MyClass.new obj.my_method # => [:v3] obj.my_method # => [:v3] local_variables # => [:v1, :obj]OK, 解释这个例子: 像Java或者C#, 允许一个inner scope去看到来自于outer scope的变量。但是这种情况在Ruby里是绝对不会发生的。一旦你开辟了新的作用域,前一个作用域中的binding数据都会被新的域的binding数据简单的覆盖,这是最重要的一点。Scope Gates 实际有下面三个地方是scope变换的场景: Class definitions Module difinitions Methods 然后这三个地方都会被关键字标记为scope边界:class, module, def 他们的行为像极了Scope Gates. (作用域开关)拿上个例子来说:v1 = 1 class MyClass # SCOPE GATE: entering class v2 = 2 local_variables # => ["v2"] def my_method # SCOPE GATE: entering def v3 = 3 local_variables end # SCOPE GATE: leaving def local_variables # => ["v2"] end # SCOPE GATE: leaving class obj = MyClass.new obj.my_method # => [:v3] obj.my_method # => [:v3] local_variables # => [:v1, :obj]这样就容易理解了, 那段代码打开了4个独立的scope:a, the top-level scopeb, a new scope when it enters MyClassc, one new scope each time it calls my_method() (调用了2次,所以就是2个new scope)这里, class ,module 跟 def 还有点微妙的区别。 class 或者 module的定义是立即被执行的, 而def正好相反,当你调用这个方法的时候才会被执行。插播: Global Variables and Top-level Instance Variables Global Variables可以访问任何scope。def a_scope $var = "some value" end def another_scope $var end a_scope #=> "some value" another_scope #=> "some value"
全局变量的问题是:系统的任何地方都可以改变它, 所以当我们跟踪它的改变就变得十分困难。所以普遍的规则是: 谨慎的使用它, 能不用就不用。有时你可以用一个顶级的实例变量来代替全局变量:@var = "The top-level @var"def my_method @var end
my_method # => "The top-level @var"Flattening the scope 当你越精通Ruby,你就会觉得想通过scope gate传递绑定数据越发困难 , 冏!my_var = "Success" class MyClass # We want to print my_var here... def my_method # ..and here end end问题: 你怎么样能把my_var变量传递到class里? 解决方案:my_var = "Success" MyClass = Class.new do # Now we can print my_var here... puts "#{my_var} in the class definition!" def my_method # ...but how can we print it here? end end MyClass.new.my_method我们使用了block的闭包,巧妙的实现了flattening scope。Sharing the scope 有时候我们可能需要让某些方法共用一个本地变量,而不让其他方法使用,那么我们可以这么做:def define_methods shared = 0 Kernel.send :define_method, :counter do shared end Kernel.send :define_method, :inc do |x| shared += x end end define_methods counter # => 0 inc(4) counter # => 4这样, 在scope gate的保护下, 其他方法是肯定无法访问本地变量shared的。4 instance_eval()instance_eval()和class_eval()常常让很多人产生误解:instance_eval()方法做了下面3件事情: a,改变self为instance_eval的接收器 b,改变默认的definee给接收器的eigenclass,如果没有,则创建它。 c, 执行block的内容。 class_eval and instance_eval 区别 self default definee class_eval the receiver the receiver instance_eval the receiver eigenclass of the receiver主要是要注意方法接收器!!!instance_exec() 这个方法是Ruby1.9引入的,行为和instance_eval()差不多,但是它允许你传入一个参数,例:class C def initialize @x, @y = 1, 2 end end C.new.instance_exec(3) {|arg| (@x + @y) * arg } # => 9Breaking Encapsulation instance_eval这种特性很恐怖, 在它的眼皮子底下,根本没有隐私可言。The Rspec Example:Clean Rooms:class CleanRoom def complex_calculation # ... end def do_something # ... end end clean_room = CleanRoom.new clean_room.instance_eval do if complex_calculation > 10 do_something end end有时候你需要创建一个对象, 只是在block里执行一些方法。那么就保持一个干净的房间, 战斗场就在block里吧。5 Callabel Objects 在Ruby里, 你至少有3个地方可以打包代码: Proc Lambda MethodProc Objects 虽然说,Ruby一切皆对象,但blocks不是对象。但是为了实现把代码打包, 等需要的时候再调用的目的(这个技术叫做Deferred evaluation,延迟求值),我们需要一个对象。这样就出现了Proc类。 一个Proc是转换为对象的block。Ruby提供了3种方法去把block转换成Proc对象。 lambda()和proc(), Proc.new()The & Operator &操作符def math(a, b) yield(a, b) end def teach_math(a, b, &operation) puts "Let's do the math:" puts math(a, b, &operation) end teach_math(2, 3) {|x, y| x * y} # => Let's do the math: # => 6你可以通过&操作符来转换block为一个Proc对象。def my_method(&the_proc) the_proc end p = my_method {|name| "Hello, #{name}!" } puts p.class # => Proc puts p.call("Bill" ) #=> Hello, Bill现在知道好多block转Proc的方法,但是你怎么转回去呢?def my_method(greeting) puts "#{greeting}, #{yield}!" end my_proc = proc { "Bill" } my_method("Hello" , &my_proc)当你在my_method方法里使用&操作符的时候,就会把my_proc这个Proc转回去block。The HighLine Example: ruby gem highlineProc vs. Lambdas 插播:Ruby1.9引入一个方法:Proc#lambda?() 用来判断一个Proc是否是lambda。区别一: return: lambda里面的return会被劫持,也就是说, 在lambda里的return只是return出lambda(因为lambda的行为似方法)。而Proc则是return出方法外。区别二: 参数: p = Proc.new {|a, b| a, b} p.arity #=> 2lambda会检查参数个数以及类型 Proc则不会检查参数个数,但会检查参数类型。Kernel#proc callable = proc { return } callable.call #=> fails in Ruby1.9在Ruby1.8里Kernel#proc()方法只是lambda的一个别名。 而在Ruby1.9里, Kernel#proc()变成了Proc.new的别名。 所以这个地方使用要区别开Ruby的版本。这个地方真的是乱七八糟的。Methods Revisited 最后一个callable objects家族成员 : methodsclass MyClass def initialize(value) @x = value end def my_method @x end end object = MyClass.new(1) m = object.method :my_method #=> m是个方法对象:#Method: MyClass#my_method m.call # => 1methods和lambda有点相似,但是不同的是, lambda是个闭包,作用域在定义它的时候上下文, 而methods的作用域是在它的对象中。 你也可以用Method#unbind()从对象里分离一个方法出来,然后把它绑定给另一个对象: unbound = m.unbind another_object = MyClass.new(2) m = unbound.bind(another_object) m.call # => 2你也可以使用Method#to_proc转换一个方法对象为一个Proc对象,并且你可以用define_method()转换一个block为一个method。6 Writing a Domain-Specific LanguageYour First DSL 见first_dsl.rb (收起)2011-03-22 23:27:02 回应
-
第209页
#chapter 8 之前的记录不了了,从这里开始继续写笔记 1.一般module使用两种办法来扩展包含他的类 a.定义方法,当包含的时候这些方法就成为了对应的类的instance method,这是module和include最直接的作用 b.定义hook_method self.included,当被包含的时候会自动执行到,这个时候可以做一些事情,比如扩展被包含类的eigenclass来扩展类方法,通过alias_method修改原来该类的一些方法的行为 2.如果从写了method_mis... (更多)#chapter 8之前的记录不了了,从这里开始继续写笔记1.一般module使用两种办法来扩展包含他的类 a.定义方法,当包含的时候这些方法就成为了对应的类的instance method,这是module和include最直接的作用 b.定义hook_method self.included,当被包含的时候会自动执行到,这个时候可以做一些事情,比如扩展被包含类的eigenclass来扩展类方法,通过alias_method修改原来该类的一些方法的行为2.如果从写了method_missing,调用private方法的时候,会调到method_missing,不写method_missing的时候是NoMethodError但是会说明是private method call笔记两个方法Array#rejectArray#combination (收起)2012-02-06 10:06:17 2回应
-
第133页
singleton method && eigenclass ##全书的重点来了## 1.class macro class M def self.deprecate(old_name,new_name) define_method(old_name) do |*args,&block| warn "xxx" send(new_mehthod,*args,&block) end end deprecate :GetTitle,:title deprecate :GetTitle,:title deprecate :GetTitle,:title ... (更多)singleton method && eigenclass##全书的重点来了##1.class macroclass M def self.deprecate(old_name,new_name) define_method(old_name) do |*args,&block| warn "xxx" send(new_mehthod,*args,&block) end end deprecate :GetTitle,:title deprecate :GetTitle,:title deprecate :GetTitle,:title end2.eigenclassclass << obj # just entered the eigenclass scope of obj,endobj = Object.newec = class << obj selfendeigenclass.class #classdef obj.s_method ;endec.instance_methods.grep /s/ # s_method##class_eval 改变当前的self和class,class为当前obj的class##instance_eval 改变当前的self和class,class为当前obj的eigenclass所以在instance_eval里面用def定义的方法是定义在其eigenclass上的instance方法所以obj才能继续使用比较一下代码o = Class.newo.instance_eval { //用def定义的方法都在当前scope的class上,instane_eval把当前的class设置为eigenclass了 def m p "m" end //self是指o,self.z也是o的eigenclass上面的方法 def self.z p "z" end 这是唯一一个def t和def self.t都是统一个方法的地方}o.m #m 改变当前的class,所以定义了当前的eigenclass的实例方法,o为其实例,可以调用o.z #z 改变当前的self,定义在self上的方法即使定义在o的eigenclass上面的方法Object.class_eval do def eigenclass class << self self end endend (收起)2012-01-17 18:29:17 2回应
-
第131页
class 关键词的等价定义 c = Class.new(Array) do #now you entered the class scope def m #instance method end end M = c #M represent the class 此时c.name会被定义成M,这是ruby内部做的处理,除了赋值以外的另外一个副作用 而且只有在c c.name #M T = c c.name #M T.name #M c.instance_eval {@name = nil} c.name #M ##so what the fuck ? (更多)class 关键词的等价定义c = Class.new(Array) do #now you entered the class scope def m #instance method endendM = c #M represent the class 此时c.name会被定义成M,这是ruby内部做的处理,除了赋值以外的另外一个副作用而且只有在cc.name #MT = cc.name #MT.name #Mc.instance_eval {@name = nil}c.name #M ##so what the fuck ? (收起)2012-01-17 18:21:43 回应
书评 · · · · · · 我来评论这本书
热门评论 最新评论
ruby王国殿堂之路
-
- 琳琳的小狗(早起的虫儿被鸟吃……) 刚读完这本书,欣喜之情溢于言表。 薄薄的一本书,把ruby对象模型、以及围绕此核心而来的各种高级技巧都讲透了,原理讲了不说,还外带把现实中的应用也一并列举了出来,让你不懂都不行:) 我喜欢这本书,不管你是初级入门还是中高级ruby程序员,此书都必须一读!注意不是值得一读,是必须!new bie,不要看到Me...... (5回应)2010-02-24 5/5有用
学ruby的都应该看看此书
-
- 鹿鸣 此书不是基本入门书,但是想更好的应用ruby,在看完ruby基础后,应该看看此书,了解ruby真正的动态化威力。 现在感觉做DSL,最方便的就是ruby了,因为有很多内置的方法就很适合元编程。 前面两章,我看得这里的翻译,翻译的还不错,后面的就看网上的e文版,好在这本书的英文算不上很复杂,基本能看通。 需要了解元......2012-01-07 来自 华中科技大学出版社2012版
一本不一样的Ruby书,因为讲的是Metaprogramming
-
- Thyrlian 作者风格:自娱自乐,尤其喜欢描写新人和导师之间的对白动作,什么“导师掏出上衣口袋的纸巾擦擦汗”,”丢下了键盘,跑到会议室“之类的,感觉像小说。 不过,从章节划分,细节讨论来说,非常不错。用了不少典型库的代码段来说明如此设计的目的,加上对一些陷阱的提问,面面俱到。 此书的部分内容和Ruby Best Prac......2011-04-28
"Metaprogramming Ruby"的论坛 · · · · · ·
- 华中科技大学出版社版 北发图书网 RMB 39.20
- 加入购书单 多本比价 批量购买 已在购书单
这本书的其他版本有售 · · · · · ·
- > 点这儿转让 有131人想读,手里有一本闲着?
这本书的其他版本 · · · · · · ( 全部2 )
- 华中科技大学出版社版 2012-1-10 / 11人读过 / 有售
以下豆列推荐 · · · · · · (全部)
- 深入Ruby/Rails系列 (RoBeRt)
- 软件 IT 经典 (uncutstone)
- Ruby与Rails新手慎入 (阳志平)
- Ruby & Rails Books (404)
- Ruby/Rails进阶必读 (琳琳的小狗)
谁读这本书?
喜欢这本书的人关注的活动 · · · · · ·
订阅关于Metaprogramming Ruby的评论:
feed: rss 2.0











