`
rainlife
  • 浏览: 229923 次
  • 性别: Icon_minigender_1
  • 来自: 我也来自火星?
社区版块
存档分类
最新评论

ruby动态编程

阅读更多
Ruby 动态编程
在介绍ruby动态编程之前,首先看一下,什么叫“动态”语言:

维基百科 写道
动态语言就是一种在运行时可以改变其结构的语言:例如新的函数可以被引进,已有的函数可以被删除等在结构上的变化。众所周知的ECMAScript(JavaScript)便是一个动态语言,除此之外如PHP、Ruby、Python等也都属于动态语言,而C、C++等语言则不属于动态语言。


在大部分的编译语言和解释语言中,编写程序和运行程序是两个截然不同的操作,换句话说,编写的代码是确定的,在运行的时候,可能需要对其进行修改。这对于ruby来说非常简单,一个ruby程序,可以在运行的过程中进行修改,甚至可以加入新的代码并且运行,而不需要重新运行该程序。
这种能够修改可执行应用程序数据的能力就叫做元编程。
维基百科 写道
元编程是指某类[计算机程序]的编写,这类计算机程序编写或者操纵其他程序(或者自身)作为它们的数据,或者在[运行时]完成部分本应在[编译时]完成的工作。很多情况下比手工编写全部代码相比工作效率更高。编写元程序的语言称之为元语言,被操作的语言称之为目标语言。一门语言同时也是自身的元语言的能力称之为反射。


在ruby代码中,其实我们一直都在进行元编程,虽然可能只是一句非常简单的代码,比如说,在“”中嵌入一个表达式,这就是元编程。毕竟,嵌入的的表达式并非真正的代码,它只是一个字符串,但是ruby却可以将它转换成真正的ruby代码并执行它。
大多数情况下,可以在双引号分隔的字符串中嵌入一些简单的以“#{”和“}”分隔的代码,通常会嵌入一个变量,或是一个表达式:
aStr = 'hello world' 
puts( "#{aStr}" ) 
puts( "#{2*10}" )

但是在实际情况中并不能满足于如果简单的表达式,如意愿意的话,应该可以在“”字符串中嵌入任何东西,甚至不需要使用print或puts来显示最终的结果。只要将字符串放置到程序中,ruby就会执行它:
	"#{def x(s)
       puts(s.upcase)
    	end;
 (1..3).each{x('hello')}}"

在一个字符串中写出一整个程序可能需要相当的努力。然而,在某些场合,这些功能可能会更有效率。例如,在rails中使用了大量的元编程。事实上,任何程序都将因为可以在程序执行过程中修改程序的行为而受益,这也是元编程最重要的意义。

动态(元编程)特性在RUBY中无处不在。例如,attribute accessors,attr_accessor :aValue就导致了 aValue 和 aValue= 两个方法被创建

eval魔法

在介绍ruby中eval之前,先来看一下大家都比较熟悉的javascript中的eval方法:

w3cschool 写道
The eval() function evaluates a string and executes it as if it was script code.                 
这个函数可以把一个字符串当作一个JavaScript表达式一样去执行它。

在ruby中,eval方法同样地,提供了在字符串中执行ruby表达式的功能。乍看之下,eval方法同在字符串中嵌入#{}的作用一样:
puts( eval("1 + 2" ) ) 
puts( "#{1 + 2}" )

但是,有些时候,结果却并非想象的那样,考虑下面的例子:
exp = gets().chomp() 
puts( eval( exp )) 
puts( "#{exp}" )

假如键入2*4并赋值给变量exp。当使用eval执行exp后结果为8。当使用执行#{ exp }后,结果为“2*4”。这是因为,通过gets()方法接收到的是一个字符串,“#{ }”将它当成字符串处理,而不是一个表达式,但是eval( exp )将它作为一个表达式处理。
为了能够在字符串中执行,需要在字符串中使用eval方法。(尽管可能会使对象执行失败)
puts( "#{eval(exp)}" )

下面是另一个示例:
print( "Enter the name of a string method (e.g. reverse or upcase): " ) 
                                         # user enters: upcase 
methodname = gets().chomp() 
exp2 = "'Hello world'."<< methodname 
puts( eval( exp2 ) )                     #=> HELLO WORLD 
puts( "#{exp2}" )                        #=> “Hello world”.upcase 
puts( "#{eval(exp2)}" )                  #=> HELLO WORLD

eval方法也可以执行多行字符串,可以用来执行嵌在字符串中的整个程序:
eval( 'def aMethod( x )
   return( x * 2 )
end
 
num = 100
puts( "This is the result of the calculation:" )
puts( aMethod( num ))' )


根据eval的特性,看一下下面的程序:
input = ""
until input == "q"
   input = gets().chomp()
   if input != "q" then eval( input ) end
end


虽然代码并不是太多,但这个小程序可以让你在命令行中创建和执行实际可运行的ruby代码。试着输入下面两个方法(不能输入’q’):
def x(aStr); puts(aStr.upcase);end 
def y(aStr); puts(aStr.reverse);end

注意你必须在命令行输入全部的方法,程序会分析刚才输入的方法,eval方法转换刚才输入的方法为真实的可执行的ruby代码。可以输入下面的代码去校验一下:
x("hello world") 
y("hello world")

输入结果为:

>>x('hello world')
>>HELLO WORLD
>>y('hello world')
>>dlrow olleh

eval的特殊类型

eval还有几个方法变体:instance_eval, module_eval, class_eval。
instance_eval方法可以通对对象调用,它提供了访问对象实例变量的能力。instance_eval可以通过代码块或是字符串调用:
class MyClass 
 def initialize 
   @aVar = "Hello world" 
 end 
end 
 
ob = MyClass.new 
p( ob.instance_eval { @aVar } )            #=> "Hello world" 
p( ob.instance_eval( "@aVar" ) )            #=> "Hello world"

另外,eval方法不能访问对象中私有的方法(尽管instance_eval方法是公有的)。不过,你可以通过调用public :eval方法明确地改变eval方法的访问属性。但是胡乱地改变基类方法的访问属性并不被推荐。
(严格地说,eval是核心模块的功能并混入到Object类中。)
你可以改变eval方法的访问属性,通过在Object类中添加下面的定义:
class Object 
   public :eval 
end 

当然,当编写独立的代码时,都处于Object类的生命周期内,只需要简单地输入下面的代码(没有Object类的包装),就可以达到同样的效果:
  
 public :eval 

现在可以通过ob实例来调用eval方法:
p( ob.eval( "@aVar" ) )                #=> "Hello world"

module_eval,class_eval方法用于模块和类上操作。例如,下面的代码在模块X中添加xyz方法(xyz方法在一个代码块中通过define_method方法定义,并作为X模块的实例方法),在类Y中添加abc方法:
module X 
end 
 
class Y 
  @@x = 10 
  include X 
end 
 
X::module_eval{ define_method(:xyz){ puts("hello" ) } } 
Y::class_eval{ define_method(:abc){ puts("hello, hello" ) } } 

所以,Y的实例就拥有了abc方法,和由X模块混入的xyz方法:
ob = Y.new 
ob.xyz                  #=> “hello” 
ob.abc                  #=> “hello, hello”

不管它们的名字,module_eval和class_eval在功能上完全相同,并且可以都可以用在模块或者类中:
X::class_eval{ define_method(:xyz2){ puts("hello again" ) } } 
Y::module_eval{ define_method(:abc2){ puts("hello, hello again" ) } } 

当然也可以以同样的方式给ruby标准类添加方法:
String::class_eval{ define_method(:bye){ puts("goodbye" ) } } 
"Hello".bye            #=> “goodbye” 


添加变量和方法

module_eval和class_eval同样可以用来接收变量的值(但是需要记住,这会加强对具体实现类的依赖,破坏了封装性):
Y.class_eval( "@@x" )  #=>10


事实上,class_eval可以执行随意复杂的表达式。例如可以通过一个字符串来添加一个新的方法:
ob = X.new 
X.class_eval( 'def hi;puts("hello");end' ) 
ob.hi               #=> “hello”


考虑刚才的在类的外部增加和调用变量的例子(使用class_eval);事实上,在类的内部也提供了同样的方法。这个方法就是 class_variable_get( 该方法接接受一个参数:变量名)和class_variable_set(该方法接受两个参数,第一个参数为变量名,第二个参数为变量的值),下面是使用 这两个方法的示例:

class X
  @@aParam = 1000

  def self.addvar( aSymbol, aValue )
    class_variable_set( aSymbol, aValue )
  end

  def self.getvar( aSymbol )
    return class_variable_get( aSymbol )
  end
end

X.addvar( :@@newvar, 2000 )
puts( X.getvar( :@@newvar ) )   #=> 2000

puts( X.getvar( :@@aParam ) )


可以通过class_variables方法返回一个包含所有类变量的数组:
p( X.class_variables )      #=> ["@@abc", "@@newvar"]


当然,也可通过instance_variable_set方法,来为类的实例添加实例变量:
ob = X.new 
ob.instance_variable_set("@aname", "Bert")
p ob.instance_variable_get("@aname")     #=> "Bert"


通过组合这些能力,程序员可以在外部完全更改类的结构。例如,可以为类X定义一个addMehtod方法,通过参数m(方法名), 参数&block(方法体)来动态地添加方法:

def addMethod( m, &block ) 
   self.class.send( :define_method, m , &block ) 
end

(send方法会根据第一个参数辨认出相应的方法并调用,并且将其它参数传递给该方法。)

现在,X对象可以调用addMehtod方法给X类增加一个新的方法:
ob.addMethod( :xyz ) { puts("My name is #{@aname}") }


尽管addMethod这个方法是由一个具体的实例调用的(这里是ob这个实例),但它的作用针对的却是这个类,所以该类的其它实例(如ob2),也可以调用由ob实例所添加的新方法:
ob2 = X.new 
ob2.instance_variable_set("@aname", "Mary") 
ob2.xyz   #=> My name is Mary


如果不考虑数据的封装性,可以通过实例的instance_variable_get方法来取得实例变量的值:
ob2.instance_variable_get( :@aname )


同样地,也可以设置和获取常数的值:
X::const_set( :NUM, 500 ) 
puts( X::const_get( :NUM ) )


既然const_get可以返回一个常量的值,那么就可以通过这个方法来得到一个类的名字,然后使用这个类名,并通过new方法来创建这个类实例。这样就可以在运行时通过提示用户输入相应的类名或方法名来动态地创建类实例以及调用相应的方法:
class X 
   def y 
      puts( "ymethod" ) 
   end 
end 
 
print( "Enter a class name: ")                           #<= Enter: X 
cname = gets().chomp 
ob = Object.const_get(cname).new 
p( ob ) 
print( "Enter a method to be called: " )              #<= Enter: y 
mname = gets().chomp 
ob.method(mname).call


运行时刻创建类

在上面,我们已经可以修改类的结构,或者创建一个类的实例,但是,我们是否可以在运行时创建一个全新的类?正像const_get可以访问存在的类一 样,const_set方法就可以用来创建一个新的类。下面这个示例将提示用户输入类名,然后创建类,添加一个方法(方法名为myname),创建类的实 例,然后调用刚才添加的方法:
puts("What shall we call this class? ") 
className = gets.strip().capitalize() 
Object.const_set(className,Class.new)           
puts("I'll give it a method called 'myname'" ) 
className = Object.const_get(className) 
className::module_eval{ define_method(:myname){  
   puts("The name of my class is '#{self.class}'" ) }  
   } 
x = className.new 
x.myname


绑定

eval方法有一个可选的参数--binding,如果为指定的话,那么表达式的值就会是一个具体的范围或上下文环境绑定。不过不必为这个有所意外,在 Ruby中,binding方法会返回一个Binding对象的实例,可以使用binding方法返回绑定的值。下是是ruby文档中提供的一个示例:
def getBinding(str) 
   return binding() 
end 
str = "hello" 
puts( eval( "str + ' Fred'" )   )                                     #=> "hello Fred" 
puts( eval( "str + ' Fred'", getBinding("bye") ) )              #=> "bye Fred"


binding方法是内核的一个私有方法。getBinding方法通过调用binding方法返回当前上下文环境中str的值。在第一次调用eval方 法的时候,当前上下文环境是main对象,并且str的值就是定义的局部变量str的值。在第二次调用eval方法是,当前的上下文环境则是 getBinding方法内部,局部变量str的值现在则为getBinding方法中参数str的值。Binding方法经常作为eval的第二个参数,这样eval就不会因为找不到变量而出错了。

上下文环境也可以在类中定义。在下面的例子中,可以看到,实例变量@mystr和类变量@@x根据类而不同:

class MyClass
   @@x = " x"
   def initialize(s)
      @mystr = s
   end
   def getBinding
      return binding()
   end
end

class MyOtherClass
   @@x = " y"
   def initialize(s)
      @mystr = s
   end
   def getBinding
      return binding() 
   end
end

@mystr = self.inspect
@@x = " some other value"

ob1 = MyClass.new("ob1 string")
ob2 = MyClass.new("ob2 string")
ob3 = MyOtherClass.new("ob3 string")
puts(eval("@mystr << @@x", ob1.getBinding))  #=> ob1 string x
puts(eval("@mystr << @@x", ob2.getBinding))  #=> ob2 string x
puts(eval("@mystr << @@x", ob3.getBinding))  #=> ob3 string y
puts(eval("@mystr << @@x", binding))             #=> main some other value



SEND

可以使用send方法来调用参数指定的方法:
name = "Fred"
puts( name.send( :reverse ) )      #=> derF
puts( name.send( :upcase ) )       #=> FRED


尽管文档规定send方法必须需要一个方法符号作为参数,但是也可以直接使用一个字符串作为参数,或者,为了保持一致,也可以使用to_sym进行方法名称进行相应的转换后调用:
name = MyString.new( gets() )     # 输入upcase
methodname = gets().chomp.to_sym               #<= to_sym 并非必需,输入upcase
puts name.send(methodname)                     #=>UPCASE


下面的这个例子显示在运行状态中通过send方法动态地执行指定的方法:
class MyString < String
  def initialize( aStr )
    super aStr
  end

  def show
    puts self
  end
  def rev
    puts self.reverse
  end
end

print("Enter your name: ")                     #<= Enter: Fred
name = MyString.new( gets() )
print("Enter a method name: " )                #<= Enter: rev
methodname = gets().chomp.to_sym
puts( name.send(methodname) )                  #=> derF


回忆一下上面使用define_method来创建方法的例子,传递了方法的名称m,还为要创建的新方法传递了一个代码块@block

def addMethod( m, &block ) 
   self.class.send( :define_method, m , &block ) 
end


移除方法

除了创建新的方法,有的时候你可能需要移除现有的方法。可以在方法内部使用remove_method方法完成,这将为移除指定的方法:
puts( "hello".reverse ) 
class String 
   remove_method( :reverse ) 
end 
puts( "hello".reverse )     #=> „undefined method‟ error!


但是如果子类重写父类的方法,在子类中通过remove_method移除该方法,但父类的方法不会被移除:

class Y 
   def somemethod 
      puts("Y's somemethod") 
   end 
end 
 
class Z < Y 
   def somemethod 
      puts("Z's somemethod") 
   end    
end 
 
zob = Z.new 
zob.somemethod                                   #=> “Z‟s somemethod” 
 
class Z 
   remove_method( :somemethod )    
end 
 
zob.somemethod                                   #=> “Y‟s somemethod”


相比之下,undef_method方法,就可以避免由于父子类之间存在相同名称的方法而造成最终调用了父类的方法:
zob = Z.new 
zob.somemethod                                   #=> “Z‟s somemethod” 
 
class Z 
   undef_method( :somemethod )           
end 
 
zob.somemethod                                   #=> „undefined method‟ error



处理丢失的方法

当ruby试着去调用一个不存在的方法时( 或者,一个对象发送了一个不能被处理的消息 ),就可能会引起错误并造成程序的终止。你可能更喜欢你编写的程序能够从这样的错误中恢复过来。可以使用method_missing方法,该方法接受一 个方法名,如果该方法不存在,method_missing方法就会被调用:
def method_missing( methodname )
   puts( "#{methodname} does not exist" )
end

xxx #=>xxx does not exist


method_missing也可以处理还有参数的根本就不存在的方法:

def method_missing( methodname, *args ) 
      puts( "Class #{self.class} does not understand: 
                            #{methodname}( #{args.inspect} )" ) 
end 


method_missing方法甚至可以动态地创建没有定义的方法:

def method_missing( methodname, *args ) 
       self.class.send( :define_method, methodname,  
                  lambda{ |*args| puts( args.inspect) } ) 
end 
 

冻结对象

上面讲了许多修改对象的方法,这样对象就可以会在无意中被修改而造成一些不希望结果。事实上,可以使用freeze方法来冻结对象的状态。一旦对象被冻结了,那么任何对此对象的修改,都会引发一个TypeError
异常。注意,一旦对象被冻结,将不能够解冻。

s = "Hello" 
s << " world" 
s.freeze 
s << " !!!"     # Error: "can't modify frozen string (TypeError)" 



可以使用frozen?方法来检查对象是否被冻结:
a = [1,2,3] 
a.freeze 
if !(a.frozen?) then 
   a << [4,5,6] 
end 


frozen方法也可以用来直接冻结一个类(如上面使用的X):
X.freeze 

分享到:
评论
12 楼 yandongdiy123 2009-10-02  
define_method(name) { ... }
定义名为name的实例方法。method可以是Proc、Method或UnboundMethod这三者之一的实例。当指定了method参数时,就返回该参数。若带块调用时,会将块变成Proc化对象,然后返回该对象。

例:

class Foo
  def foo() p :foo end
  define_method(:bar, instance_method(:foo))
end
Foo.new.bar    # => :foo

带块调用时,各版本的处理方式不尽相同。在Ruby 1.7以后的版本中,在执行新定义的方法时,将会在receiver类的实例的基础上对块执行instance_eval。而在Ruby 1.6版本中,只是在块与方法之间取得关联,在执行新定义的方法时,块只是运行在生成时的context中。请参考下例。

class C
end
# 定义实例方法 print_self 。
# 但因为 define_method 是私有方法
# 所以不能直接调用。必须借助于 __send__ 来进行调用。
C.__send__(:define_method, :print_self) { p self }

# 在 1.6 版本中
C.new.print_self    #=> main
# 在 1.7 版本中
C.new.print_self    #=> #<C:0x4015b490>

11 楼 yandongdiy123 2009-10-02  
在类内用define_methods定义一个实例方法,传入闭包内有self,该self为什么不是表示定义它的类上下文?
Person = Class.new 
p1 = Person.new 
puts p1.class #Person

class Person  
  define_method :who? do 
    puts self
  end 
end
p1.who?
#<Person:0xb8bcdb4>
10 楼 meladet 2009-08-12  
好文章,讲得很全很系统
9 楼 rainlife 2009-05-07  
wolfplanet 写道
我可是全都看完了,发现了个小错
引用
ob = X.new 
ob.instance_variable_set("@aname", "Bert")
p ob.instance_variable_set("@aname")     #=> "Bert"


下面的那个应该是instance_variable_get 

确实应该是instance_variable_get,谢谢指出,已经改正。
8 楼 wolfplanet 2009-05-06  
我可是全都看完了,发现了个小错
引用
ob = X.new 
ob.instance_variable_set("@aname", "Bert")
p ob.instance_variable_set("@aname")     #=> "Bert"


下面的那个应该是instance_variable_get 
7 楼 weskycn 2009-05-04  
aone 写道
看完了.但绑定那块没太明白.

绑定 还是讲的比较清楚的,受益良多
6 楼 RednaxelaFX 2009-04-28  
好文~

rainlife 写道
在ruby代码中,其实我们一直都在进行元编程,虽然可能只是一句非常简单的代码,比如说,在“”中嵌入一个表达式,这就是元编程。毕竟,嵌入的的表达式并非真正的代码,它只是一个字符串,但是ruby却可以将它转换成真正的ruby代码并执行它。
大多数情况下,可以在双引号分隔的字符串中嵌入一些简单的以“#{”和“}”分隔的代码,通常会嵌入一个变量,或是一个表达式

Ruby的string interpolation,字符串插值应该还算不上元编程吧。至少Ruby的字符串插值并不带来任何“程序操纵或改变程序”的能力。
在调用Ruby的eval时,作为参数传给eval的字符串就是普通的字符串,在Ruby解析源码的时候不会做任何特殊的处理。而使用#{}形式(及其简写形式)的字符串插值时,Ruby解析器会为插值代码生成对应的AST,保存在一个NODE_EVSTR里。
可以简单的验证它们行为的差别:
puts 'start'
puts "#{1 +* 2}" # 这段插值代码有语法错误
puts 'end'

puts 'start'
puts eval('1 +* 2') # 这段传给eval的参数中代码有语法错误
puts 'end'

可以观察到前者在还没有输出start就报语法错了,而后者是输出start之后才报语法错。这是解析时机的差异造成的,也显示了Ruby的字符串插值中的代码并不“只是一个字符串”。
5 楼 night_stalker 2009-04-28  
aone 写道

为什么不一样呢?ruby版本问题?我1.8.6


你少了 #{ 和 }
4 楼 aone 2009-04-28  
C:\Documents and Settings\w>irb
irb(main):001:0> "def x(s);puts(s.upcase);end;(1..3).each{x('hello')}"
=> "def x(s);puts(s.upcase);end;(1..3).each{x('hello')}"
irb(main):002:0> "def x(s)
irb(main):003:0" puts(s.upcase)
irb(main):004:0" end;
irb(main):005:0" (1..3).each{x('hello')}"
=> "def x(s)\nputs(s.upcase)\nend;\n(1..3).each{x('hello')}"
irb(main):006:0>
irb(main):007:0*
irb(main):008:0* eval("def x(s);puts(s.upcase);end;(1..3).each{x('hello')}")
HELLO
HELLO
HELLO
=> 1..3
irb(main):009:0>


为什么不一样呢?ruby版本问题?我1.8.6
3 楼 Hooopo 2009-04-28  
aone 写道
"def x(s)
  puts(s.upcase)
end;
(1..3).each { x('hello')  }"

引用
只要将字符串放置到程序中,ruby就会执行它


会吗?我试了要eval才行.

这个例子不需要eval吧?我试过结果是:

C:\Documents and Settings\xp2008>irb
irb(main):001:0> "#{def x(s)
irb(main):002:0"        puts(s.upcase)
irb(main):003:0"     end;
irb(main):004:0"  (1..3).each{x('hello')}}"
HELLO
HELLO
HELLO
=> "1..3"

2 楼 aone 2009-04-28  
看完了.但绑定那块没太明白.
1 楼 aone 2009-04-28  
"def x(s)
  puts(s.upcase)
end;
(1..3).each { x('hello')  }"

引用
只要将字符串放置到程序中,ruby就会执行它


会吗?我试了要eval才行.

相关推荐

    Ruby动态编程对象编程Ruby动态编程对象编程Ruby动态编程对象编程

    Ruby是一门简洁、灵活而又优雅的动态编程语言,由日本开发者松本行弘(Yukihiro Matsumoto)于1993年创造。Ruby以其易读易写的语法、强大的面向对象编程和丰富的生态系统而备受开发人员的喜爱。本文将为您介绍Ruby的...

    Ruby动态编程语言v2.6.3

    Ruby是一种跨平台、面向对象的动态类型编程语言。Ruby 体现了表达的一致性和简单性,它不仅是一门编程语言,更是表达想法的一种简练方式。 Ruby 是一个注重均衡的语言,它的发明者松本行弘(Yukihiro “Matz” ...

    Ruby编程,Ruby编程,

    Ruby编程,Ruby编程,Ruby编程,Ruby编程,Ruby编程,

    Ruby元编程第二版中文

    Ruby元编程第二版,中文影印版,便于英文不好的同学们学习

    ruby元编程.pdf

    ruby元编程.pdf ruby 元编程 这本书对ruby的调用原理做了非常精辟的分析。 ruby 元编程 这本书对ruby的元编程方式做了比较好的阐释。 ruby 元编程 这本书对结对编程有一个很好的提现。

    Ruby元编程pdf

    Ruby元编程pdf

    Ruby元编程-中文

    通过分析案例、讲解例题、回顾Ruby代码库的实现细节,作者不仅向读者展示了Ruby编程的优势和Ruby特有的解决问题的方式,更详细开列出发挥其优势的技巧和常用的Ruby设计模式。Ruby之父松本行弘作 序推荐。

    《Ruby元编程》PDF版本下载.txt

    《Ruby元编程》PDF版本下载

    Ruby元编程中文版

    Ruby元编程中文版

    Ruby元编程 第2版 中文 佩罗塔著 2015.08

    ruby元编程 第2版 中文 目录清晰 方便广大通勤族路上看,如果喜欢请购买正版纸质图书

    Ruby编程语言中文版

    Ruby编程语言中文版,涵盖Ruby 1.8和Ruby 1.9

    Ruby 元编程

    本书的第一部分“Ruby元编程”是本书的核心部分,他讲述了一个资深程序员在办公室一周发生的事情。 本书的第二部分“Rails中的元编程”是一个元编程实例,Rail是Ruby标志性框架。 在阅读本书之前,需要了解本书的三...

    ruby元编程

    《Ruby元编程》以案例形式循序渐进地介绍了Ruby特有的实用编程技巧 元编程 通过分析案例 讲解例题 回顾Ruby代码库的实现细节 《Ruby元编程》作者Paolo Perrotta不仅向读者展示了Ruby编程的优势和Ruby特有的解决问题...

    Ruby并发编程框架Celluloid.zip

    Celluloid 是一个 Ruby 语言的并发面向对象编程框架,可让你轻松构建多线程程序。 标签:Celluloid

    Ruby元编程 源代码 Metaprogramming Ruby source code

    Ruby元编程 书籍配套源代码 Metaprogramming Ruby source code

    Ruby编程语言_涵盖Ruby 1.8和1.9

    Ruby编程语言_涵盖Ruby 1.8和1.9

    Ruby编程语言pdf

    在对Ruby进行了简要的综述之后,本书详细介绍了以下内容:Ruby的句法和语法结构,数据结构和对象,表达式和操作符,语句和控制结构,方法、proc、lambda和闭包,反射和元编程,Ruby平台。 本书还包含对Ruby平台上...

    Metaprogramming Ruby 2nd Edition ruby元编程

    Metaprogramming Ruby 2nd Edition ruby元编程

Global site tag (gtag.js) - Google Analytics