<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>Thinking In Ruby</title>
    <description>Ruby编程思想</description>
    <link>http://thinkinginruby.group.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
          <item>
        <title>Ruby Meta Programming: define_method or class_eval</title>
        <author>yapex</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://yapex.javaeye.com">yapex</a>&nbsp;
                    链接：<a href="http://thinkinginruby.group.javaeye.com/group/blog/220596" style="color:red;">http://thinkinginruby.group.javaeye.com/group/blog/220596</a>&nbsp;
          发表时间: 2008年07月28日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          今天刚巧看到Matt Aimonetti的blog上讨论ruby meta programming的执行效率问题，就跟着做了一下，还是学到了不少东西。大致说一下吧，首先Matt写了一个简单的计算时间的DSL类：<br /><pre name="code" class="ruby">
module TimeDSL
    def second
      self * 1
    end
    alias_method :seconds, :second

    def minute
      self * 60
    end
    alias_method :minutes, :minute

    def hour
      self * 3600
    end
    alias_method :hours, :hour

    def day
      self * 86400
    end
    alias_method :days, :day

    def week
      self * 604800
    end
    alias_method :weeks, :week

    def month
      self * 2592000
    end
    alias_method :months, :month

    def year
      self * 31471200
    end
    alias_method :years, :year
end
Numeric.send :include, TimeDSL
</pre><br /><br />这个类很简单，就是为Numeric类增加了与时间相关的一些方法，这样就可以使用类似的代码计算时间了，例如：<br /><pre name="code" class="ruby">
1.hours + 20.minutes # => 一小时20分钟是多少秒
3.days + 5.hours # => 3天零5小时
2.years + 10.months # => 两年十个月
</pre><br /><br />代码很简单，不过请大家注意Matt使用<pre name="code" class="ruby">Numeric.send :include, TimeDSL</pre>方法为Numeric类增加了TimeDSL这个模块。<br />然后他又写了一个利用define_method方式实现TimeDSL的类（为了方便说明，我略作了修改）<br /><pre name="code" class="ruby">
module BadMetaTimeDSL

    {:second => 1, 
     :minute => 60, 
     :hour => 3600, 
     :day => [24,:hours], 
     :week => [7,:days], 
     :month => [30,:days], 
     :year => [364.25, :days]}.each do |meth, amount|
		define_method "b_#{meth}" do
			amount = amount.is_a?(Array) ? amount[0].send(amount[1]) : amount
			self * amount
		end
		alias_method "b_#{meth}s".intern, "b_#{meth}"
    end
  end
Numeric.send :include, BadMetaTimeDSL
</pre><br /><br />他发布了这两个类benchmark的测试数据，并得出结论说ruby的meta programming基本上要比正常方式慢3倍左右（我自己的测试数据是2倍左右）<br />这个结论很快就引来了很多人的的讨论，最后Wycats提出了改进方案<br /><pre name="code" class="ruby">
module GoodMetaTimeDSL
  SECOND  = 1
  MINUTE  = SECOND * 60
  HOUR    = MINUTE * 60
  DAY     = HOUR * 24
  WEEK    = DAY * 7
  MONTH   = DAY * 30
  YEAR    = DAY * 364.25

  %w[SECOND MINUTE HOUR DAY WEEK MONTH YEAR].each do |const_name|
      meth = const_name.downcase
      class_eval &lt;&lt;-RUBY
        def g_#{meth}
          self * #{const_name}
        end
        alias g_#{meth}s g_#{meth}
      RUBY
  end
end
Numeric.send :include, GoodMetaTimeDSL
</pre><br />新的类执行效率直逼正常方式定义的类，可以说基本上没有太大的差异了。究其原因define_method需要创建Proc才能执行，而class_eval和ruby自身执行方式没有什么差别，都是直接解释执行。<br /><br />最后的结论是：如果可能，尽量使用class_eval进行meta programming<br /><br />不知道怎么把附件的图贴进来，大家看附件吧，也包括源代码。<br />整个测试都在jruby 1.1.3下通过<br /><br />可以参考<a href="http://railsontherun.com/2008/6/18/about-metaprogramming-speed" target="_blank">http://railsontherun.com/2008/6/18/about-metaprogramming-speed</a>
          <br/>
          <span style="color:red;">
            <a href="http://thinkinginruby.group.javaeye.com/group/blog/220596#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 28 Jul 2008 17:06:56 +0800</pubDate>
        <link>http://thinkinginruby.group.javaeye.com/group/blog/220596</link>
        <guid>http://thinkinginruby.group.javaeye.com/group/blog/220596</guid>
      </item>
          <item>
        <title>Ruby Meta Programming: eigenclass</title>
        <author>yapex</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://yapex.javaeye.com">yapex</a>&nbsp;
                    链接：<a href="http://thinkinginruby.group.javaeye.com/group/blog/220168" style="color:red;">http://thinkinginruby.group.javaeye.com/group/blog/220168</a>&nbsp;
          发表时间: 2008年07月27日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Ruby eigenclass从字面上理解就是自己的类。singleton class是它的另一个名字，不过我更喜欢eigen，更准确。<br />那什么是eigenclass呢？以x战警为例：<br /><pre name="code" class="ruby">
class Person
    attr_accessor :name, :age
    def initialize(name)
        @name = name
    end
end
</pre><br /><br />金刚狼外表看起来和普通人没什么区别，不过他有着钛合金的骨架，能够自动疗伤，而且有锋利的爪子。在这种情况下如何定义呢？ruby给了我们一个更优雅的方式解决这个问题。<br /><pre name="code" class="ruby">
logen = Person.new('Logen')
class &lt;&lt; logen
    def use_claw
        # ...
    end
end
logen.use_claw
</pre><br /><br />use_claw是一个实例方法，它只和logen实例有关系，也就是说是logen独有的。ruby为每个实例引入了一个隐式的eigenclass，所有针对这个实例的方法都定义在eigenclass中。<br /><br />要真正理解eigenclass首先要从ruby的对象模型开始，在ruby中一切都是对象，包括Class类也是对象，用下面的例子说明一下<br /><pre name="code" class="ruby">
o = Object.new
p o.class # => Object

p Class.superclass.superclass # => Object

p Object.superclass # => nil
</pre><br /><br />也就是说，实例的class是对象，而Class对象的最终的基类是Object类。<br />在Ruby中，实例对象本身不能包含方法，所有的方法都保存在与这个实例对象相关的类中。ruby的实例更像是先从eigenclass继承，然后才从class继承。ruby运行时查找方法顺序如下：<br /><ul><br />1. 在eigenclass查找实例方法<br />2. 在class中查找实例方法<br />3. 在每一个被包含的module中查找实例方法<br />4. 在基类中查找实例方法<br />5. 触发method_missing方法<br /></ul><br /><br />eigenclass更像是在解决哲学中“我是谁”这个问题：虽然你我都属于人类，可每个人都有自己唯一和独特的一面，而所有这些唯一和独特的东西都在eigenclass中定义！
          <br/>
          <span style="color:red;">
            <a href="http://thinkinginruby.group.javaeye.com/group/blog/220168#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 27 Jul 2008 18:22:36 +0800</pubDate>
        <link>http://thinkinginruby.group.javaeye.com/group/blog/220168</link>
        <guid>http://thinkinginruby.group.javaeye.com/group/blog/220168</guid>
      </item>
          <item>
        <title>Ruby/JRuby里定义类时指定基类的一个问题</title>
        <author>RednaxelaFX</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://rednaxelafx.javaeye.com">RednaxelaFX</a>&nbsp;
                    链接：<a href="http://thinkinginruby.group.javaeye.com/group/blog/203917" style="color:red;">http://thinkinginruby.group.javaeye.com/group/blog/203917</a>&nbsp;
          发表时间: 2008年06月16日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <a href="http://rednaxelafx.javaeye.com/blog/202774" target="_blank">之前的一帖</a>里提到了JRuby里Java类的名称问题。后来读到JavaEye上<a href="http://www.javaeye.com/topic/159127" target="_blank">当Ruby遇到Java，勇敢地跨越边界吧</a>这一帖，发现里面有这样的代码例子：<br /><pre name="code" class="ruby">class MyStringBuffer &lt; java.lang.StringBuffer
  def append(v)
  end
end</pre><br />然后觉得有点奇怪：为什么基类的部分用java.lang.StringBuffer就行呢？在类的名字定义那里要是写java.lang.StringBuffer明明不行的。<br /><br />后来发觉Ruby在定义类的时候，基类的部分只要是个返回Class类型的表达式就行，不一定要是具体的基类的名字。<br />在Ruby 1.8.6里测试：<br /><pre name="code" class="ruby">irb(main):001:0> class A
irb(main):002:1> end
=> nil
irb(main):003:0> class B
irb(main):004:1>   def B.a
irb(main):005:2>     A
irb(main):006:2>   end
irb(main):007:1> end
=> nil
irb(main):008:0> class C &lt; B.a
irb(main):009:1> end
=> nil
irb(main):010:0> C.superclass
=> A</pre><br />在JRuby 1.1.2里测试得到的结果是一样的。这样就可以理解为什么前面StringBuffer的例子能正确执行了。<br />但是类名的部分仍然必须是一个合法的名字，而不能是任意的表达式。
          <br/>
          <span style="color:red;">
            <a href="http://thinkinginruby.group.javaeye.com/group/blog/203917#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 16 Jun 2008 03:50:56 +0800</pubDate>
        <link>http://thinkinginruby.group.javaeye.com/group/blog/203917</link>
        <guid>http://thinkinginruby.group.javaeye.com/group/blog/203917</guid>
      </item>
          <item>
        <title>JRuby的类重定义……为什么不行？</title>
        <author>RednaxelaFX</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://rednaxelafx.javaeye.com">RednaxelaFX</a>&nbsp;
                    链接：<a href="http://thinkinginruby.group.javaeye.com/group/blog/202774" style="color:red;">http://thinkinginruby.group.javaeye.com/group/blog/202774</a>&nbsp;
          发表时间: 2008年06月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          在jirb里想试试这个的：<br /><pre name="code" class="ruby">class java.lang.Integer
  def +(rhs)
    self.int_value() + rhs
  end
end</pre><br />但是jirb总是提示self.int_value() + rhs那行有错。到底是为什么呢？<br /><br />我也就是想这样而已……<br /><pre name="code" class="ruby">irb(main):001:0> i = java.lang.Integer.new(1) # OK
irb(main):002:0> i
=> #&lt;Java::JavaLang::Integer:0x1fbc355 @java_object=1>
irb(main):003:0> i.java_class
=> java.lang.Integer
irb(main):004:0> i.int_value
=> 1
irb(main):005:0> i + 2     # not impl'd
=> 3                       # what I'd like to see</pre><br /><br />结果我发现我犯了个超低级的错误。JRuby实现java.lang.Integer这样的类型访问实际上是通过method_missing机制，先是对java这个<strong>方法</strong>进行调用，方法不存在而通过method_missing机制，转换成一个值返回过来；然后对这个<strong>返回值</strong>调用其lang<strong>方法</strong>（或者还是说“发送"lang"消息”更合适？），不存在，于是在method_missing里做了点手脚来找到对应的package并返回<strong>又一个值</strong>，再调用Integer方法，同样是不存在然后通过method_missing找到对应的Java类。<br /><br />在jirb里试试这个就知道上面说的是什么了：<br /><pre name="code" class="ruby">irb(main):001:0> java
=> Java::Java
irb(main):002:0> java()
=> Java::Java
irb(main):003:0> com
=> Java::Com
irb(main):004:0> com().sun()
=> Java::ComSun</pre><br />这里的java啊com啊什么的都<span style="color: red">不是变量</span>，而是不存在的方法而已。<br /><br />于是，java.lang.Integer只是个会返回一个值的一连串方法调用。Java::JavaLang::Integer才是这个Java类在JRuby里的名字。形式是：<br /><div class="quote_title">引用</div><div class="quote_div">Java::FullPackageNameInCamelCase::ClassName</div><br /><br />明白了这点之后，只要把上面的代码改一句就行：<br /><pre name="code" class="ruby">irb(main):001:0> class Java::JavaLang::Integer # 改了这里
irb(main):002:1>   def +(rhs)
irb(main):003:2>     self.int_value + rhs
irb(main):004:2>   end
irb(main):005:1> end
=> nil
irb(main):006:0> i = java.lang.Integer.new 2
=> #&lt;Java::JavaLang::Integer:0x7efa96 @java_object=2>
irb(main):007:0> i + 3
=> 5</pre><br /><br />T T 这种集成方法还是稍微surprise了一下。<br />不过回过头来想想，IronRuby/DLR的做法跟这个在表现上非常相似，但具体做法不同。JRuby主要通过method_missing机制，而IronRuby/dlr则通过注入全局变量：可以在host里为脚本运行环境注入一个名为System的NamespaceTracker类型全局变量，它会自动找到System下面的各个类以及各个子命名空间。我还是玩DLR的时间更多些，对IronRuby也比对JRuby更熟悉些。可惜现在的IronRuby离真正“能用”差得还好远。<br />在John Lam的blog上的一篇文章，<a href="http://www.iunknown.com/2008/03/dynamic-silve-2.html" target="_blank">Dynamic Silverlight Part 3: Integrating Silverlight with ASP.NET MVC</a>里，就有这种要在IronRuby的代码里复写.NET原有类型的方法的使用场景：<br />silverlight.rb:<br /><pre name="code" class="ruby">class UIElement
  alias_method :old_render_transform_origin=,
               :render_transform_origin=

  def render_transform_origin=(point)
    self.old_render_transform_origin = Point.new(point.first, point.last)
  end
end</pre><br />类名直接就UIElement了（多好 T T<br />UIElement是Silverlight/WPF的一个类。这里是要给RenderTransformOrigin方法写一个adaptor，让它的参数类型从WPF的Point改变为Ruby的数组，让整个类用起来更“Ruby”。很有趣。<br />当然前面是有相应的require的。JRuby在做了合适的require之后也能达到类似的效果。
          <br/>
          <span style="color:red;">
            <a href="http://thinkinginruby.group.javaeye.com/group/blog/202774#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 13 Jun 2008 05:15:07 +0800</pubDate>
        <link>http://thinkinginruby.group.javaeye.com/group/blog/202774</link>
        <guid>http://thinkinginruby.group.javaeye.com/group/blog/202774</guid>
      </item>
          <item>
        <title>Ruby 1.8.x中复合赋值运算符的实现</title>
        <author>RednaxelaFX</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://rednaxelafx.javaeye.com">RednaxelaFX</a>&nbsp;
                    链接：<a href="http://thinkinginruby.group.javaeye.com/group/blog/202334" style="color:red;">http://thinkinginruby.group.javaeye.com/group/blog/202334</a>&nbsp;
          发表时间: 2008年06月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          嗯，在RPGCHINA读帖的时候看到一个有趣的主题，说Ruby的a = a + 1与a += 1的执行效率不一样。很明显这个认识有偏差，事实上Ruby的复合赋值运算符与其展开的简单赋值形式在经过解释器前端的解析后就一模一样了。连对应的抽象语法树都是一样的，执行效率能差多少呢？<br /><br />更糟糕的是回帖中有错误的解释，将这个“差异”对应到汇编上：<br /><div class="quote_title">引用</div><div class="quote_div">引用第8楼nightaway于2008-03-12 21:33发表的&nbsp; :<br />a+=1&nbsp;&nbsp; 编译后的汇编指令&nbsp; add<br />a++&nbsp;&nbsp;&nbsp;&nbsp; 编译后的汇编指令&nbsp; inc<br />inc 的运算周期 小于 add 所以 a++ 比 a+=1 快<br /><br />如果楼主有疑问可以学学汇编语言.. 这样你的编码水平会大增..</div><br />这不是答非所问么……那帖的主题明明是在讨论a += 1与a = a + 1的差异；+=与++又不等价，况且Ruby里连++运算符都没有 =_=|||<br /><div class="quote_title">引用</div><div class="quote_div">引用第12楼jiangcq于2008-05-26 10:32发表的&nbsp; :<br />回答正确，+= 比 =&nbsp;&nbsp;&nbsp; +&nbsp;&nbsp;&nbsp; 效率要高很多，特别是在早期的计算机上<br />####################<br />a=a+1 <br />MOV&nbsp; EAX,A<br />MOV&nbsp; EBX,1<br />ADD&nbsp; EAX,EBX<br />MOV&nbsp; A,EAX<br />##################<br />a+=1<br />MOV&nbsp; EAX,A<br />INC&nbsp; EAX<br />MOV&nbsp; A,EAX<br />####################<br />如果没记错的话应该是这样计算的</div><br />诶，所以说不知道就不要乱说嗯。这MOV EBX, 1在运算支持立即数的指令集里明显是废的。<br />编译器能做的优化多的是。偏偏这a = a + 1却没什么优化可做。假如这是C代码生成为x86的目标代码，编译器选择ADD r32, #1还是INC r32与这个语句写成a = a + 1还是a += 1没什么关系……要说跟a++或者++a扯上关系那还靠谱点，不过如果是好的优化编译器都应该能生成一样的代码。<br />这复合赋值运算符最大的意义在于：1、让源代码更加简洁易读；2、减少重复的地址计算。之所以a = a + 1与a += 1无论如何也差不了多少是因为a本身就已经是一个变量了，能“直接”访问。假如这是一个需要昂贵的地址计算的表达式，那复合赋值运算符就显得很有意义了。例如这样：<br /><pre name="code" class="java">a.prop[0][1] = a.prop[0][1] + 1;</pre><br />这里要赋值的目标的地址无法直接得到，得经过复杂的计算。这种情况下取值和赋值分开两次来计算地址就比只计算一次要慢一些，因而有优化的必要。<br /><br />原帖地址：<a href="http://www.rpgchina.com/bbs/read-htm-tid-32257.html" target="_blank">http://www.rpgchina.com/bbs/read-htm-tid-32257.html</a><br /><br />要讨论这种问题果然还是得研究一下MRI到底是如何实现这些东西的。<br />YARV的实现机制比较不同，而且1.9.0这个实验系列何时才会进化到稳定版的2.0.x还很难说，所以还是拿1.8.x系列为准来讨论了。<br /><br />===========================================================================<br /><br />下面内容是我在那帖14楼的回复：<br /><br /><br />这个……事情要具体问题具体分析对吧，张冠李戴就不太好了 ^ ^<br />+=之类的复合赋值运算符在许多语言都有，语义类似但是实现的方式并不总相同。<br />RGSS里的脚本语言是Ruby，RPG Maker VX里使用的Ruby是1.8.1版的MRI。Ruby源代码并没有被直接编译到机器码，而是被Ruby解释器所解释：先把源代码翻译成抽象语法树，然后解释抽象语法树。<br />在Ruby里，一切皆是对象。因此像是加号减号之类的运算，也被看作是对象上的方法。a += 1的语义是a = a.+(1)（语义是：调用a对象上的+()方法，把1作为参数传进去，然后将方法的返回值赋值给a。更准确的说，是对右手边的a对象发送了一个"+"消息，以1为参数；返回得到的值赋值给左手边的a）。<br />+=的语义不是单独定义，而是由+()方法所决定的；换句话说一个类定义了+()方法就自动具备了+=。假如有语句a = 1，那么a是一个Fixnum，+=当中调用的+()方法就是Fixnum#+()。<br /><br />先看看"+="这个符号被解析器识别为什么了。Ruby的扫描器（词法分析器）里有这么一段：<br />parse.y<br /><pre name="code" class="java">case '+':
c = nextc();
if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
    lex_state = EXPR_ARG;
    if (c == '@') {
        return tUPLUS;
    }
    pushback(c);
    return '+';
}
if (c == '=') {
    yylval.id = '+';      // 注意这里，id是'+'
    lex_state = EXPR_BEG;
    return tOP_ASGN;      // 然后整体以tOP_ASGN返回
}</pre><br />可以看到+=被识别为tOP_ASGN类型的token。<br /><br />a += 1形式的语句对应的这条语法：<br /><pre name="code" class="java">statement: //...
    | var_lhs tOP_ASGN command_call
    // ...
    | //...
    ;</pre><br />语法对应着解析器（语法分析器），而解析器会生成抽象语法树。如果等号前的是||则语法生成NODE_OP_ASGN_OR节点，如果是&&则生成NODE_OP_ASGN_AND节点，其它则调用call_op()函数生成NODE_CALL节点。<br />parse.y<br /><pre name="code" class="java">var_lhs tOP_ASGN command_call
{
    value_expr($3);
    if ($1) {
        ID vid = $1->nd_vid;
        if ($2 == tOROP) {
            $1->nd_value = $3;
            $$ = NEW_OP_ASGN_OR(gettable(vid), $1);
            if (is_asgn_or_id(vid)) {
                $$->nd_aid = vid;
            }
        }
        else if ($2 == tANDOP) {
            $1->nd_value = $3;
            $$ = NEW_OP_ASGN_AND(gettable(vid), $1);
        }
        else {
            $$ = $1; // 获得var_lhs对应的节点
            // call_op将返回一个NODE_CALL节点，并赋值给var_lhs对应节点的“值”
            $$->nd_value = call_op(gettable(vid),$2,1,$3);
        }
    }
    else {
        $$ = 0;
    }
}</pre><br />由于节点的“值”（nd_value）被赋值为一个NODE_CALL节点，这里实质上完成了将a += 1变为a = a.+(1)的转换。<br /><br />看看a = a + 1对应的语法和动作：<br />parse.y<br /><pre name="code" class="java">lhs '=' command_call
{
    $$ = node_assign($1, $3);
}</pre><br />结合下面node_assign()函数的实现，可以看到这里是把右手边的节点赋值给了左手边节点的“值”（nd_value）。并且，右手边的a + 1对应的语法与动作如下：<br />parse.y<br /><pre name="code" class="java">arg '+' arg
{
    $$ = call_op($1, '+', 1, $3);
}</pre><br />也是调用call_op()生成NODE_CALL节点，跟前面a += 1时一样。<br />于是，a += 1与a = a + 1在被解析后所生成的语法树是一样的，后续执行中就都是等价的了。<br />parse.y<br /><pre name="code" class="java">static NODE*
node_assign(lhs, rhs)
    NODE *lhs, *rhs;
{
    if (!lhs) return 0;

    value_expr(rhs);
    switch (nd_type(lhs)) {
      case NODE_GASGN:
      case NODE_IASGN:
      case NODE_LASGN:
      case NODE_DASGN:
      case NODE_DASGN_CURR:
      case NODE_MASGN:
      case NODE_CDECL:
      case NODE_CVDECL:
      case NODE_CVASGN:
        lhs->nd_value = rhs; // 注意这里
        break;

      case NODE_ATTRASGN:
      case NODE_CALL:
        lhs->nd_args = arg_add(lhs->nd_args, rhs);
        break;

      default:
        /* should not happen */
        break;
    }

    return lhs;
}</pre><br /><br />（nd_value是在node.h里定义的一个宏，展开为u2.node）<br /><br />===========================================================================<br /><br />这是Fixnum#+()对应的C函数：<br />numeric.c<br /><pre name="code" class="java">/*
 * call-seq:
 *   fix + numeric   =>  numeric_result
 *
 * Performs addition: the class of the resulting object depends on
 * the class of &lt;code>numeric&lt;/code> and on the magnitude of the
 * result.
 */

static VALUE
fix_plus(x, y)
    VALUE x, y;
{
    if (FIXNUM_P(y)) {
	long a, b, c;
	VALUE r;

	a = FIX2LONG(x);
	b = FIX2LONG(y);
	c = a + b;
	r = LONG2NUM(c);

	return r;
    }
    if (TYPE(y) == T_FLOAT) {
	return rb_float_new((double)FIX2LONG(x) + RFLOAT(y)->value);
    }
    return rb_num_coerce_bin(x, y);
}</pre><br />该函数被注册到Ruby的类型系统中：<br />numeric.c<br /><pre name="code" class="java">rb_define_method(rb_cFixnum, "+", fix_plus, 1);</pre><br />rb_cFixnum是Ruby的Fixnum的C的实现类，继承自rb_cInteger：<br />numeric.c<br /><pre name="code" class="java">rb_cFixnum = rb_define_class("Fixnum", rb_cInteger);</pre><br />上面rb_define_method函数使得fix_plus与一个NODE_CFUNC关联在了一起。这个函数会调用rb_intern(name)来将方法名转换为ID，这里对运算符做了特殊处理：<br />parse.y<br /><pre name="code" class="java">if (name[0] != '_' && ISASCII(name[0]) && !ISALNUM(name[0])) {
    /* operators */
    int i;

    for (i=0; op_tbl[i].token; i++) {
        if (*op_tbl[i].name == *name &&
            strcmp(op_tbl[i].name, name) == 0) {
            id = op_tbl[i].token;
            goto id_regist;
        }
    }
}</pre><br />这个特殊处理可以保证运算符与内建函数的对应关系。<br /><br />P.S. 以上代码来自Ruby 1.8.7的源码。<br />P.P.S Ruby Hacking Guide真是本好书
          <br/>
          <span style="color:red;">
            <a href="http://thinkinginruby.group.javaeye.com/group/blog/202334#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 12 Jun 2008 06:53:55 +0800</pubDate>
        <link>http://thinkinginruby.group.javaeye.com/group/blog/202334</link>
        <guid>http://thinkinginruby.group.javaeye.com/group/blog/202334</guid>
      </item>
          <item>
        <title>将ANTLR生成的.tokens文件重格式化（Ruby版）-20080626更新</title>
        <author>RednaxelaFX</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://rednaxelafx.javaeye.com">RednaxelaFX</a>&nbsp;
                    链接：<a href="http://thinkinginruby.group.javaeye.com/group/blog/176731" style="color:red;">http://thinkinginruby.group.javaeye.com/group/blog/176731</a>&nbsp;
          发表时间: 2008年03月27日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          相关链接：<br /><a href="http://rednaxelafx.javaeye.com/blog/177089" target="_blank">将ANTLR生成的.tokens文件重格式化（C++版）</a><br /><a href="http://rednaxelafx.javaeye.com/blog/177092" target="_blank">将ANTLR生成的.tokens文件重格式化（C#版）</a><br /><br />ANTLR在对.g的语法文件生成Java代码的同时，还会生成一个.tokens文件来方便别的parser（例如说接在source parser后的tree parser）使用同样的token定义。<br />不过这tokens文件看起来不总是那么方便。举例来说，<a href="http://rednaxelafx.javaeye.com/blog/176524" target="_blank">昨天发的帖</a>里Dolphin.g，对应的Dolphin.tokens文件如下：<br />Dolphin.tokens:<br /><pre name="code" class="java">FUNCTION=4
NullLiteral=31
WHILE=18
FloatTypeSuffix=38
OctalLiteral=33
CharacterLiteral=28
LBRACE=11
LineComment=44
FOR=19
DO=17
Exponent=37
RelationalOperator=24
HexDigit=35
BREAK=20
Identifier=5
LPAREN=6
IF=16
AssignmentOperator=15
RPAREN=7
CONTINUE=21
Comment=43
COMMA=8
AddOperator=25
RETURN=22
TypeSpecifier=10
VAR=13
HexLiteral=32
RBRACE=12
IntegerTypeSuffix=36
SEMICOLON=14
DecimalLiteral=34
AssignmentShorthandOperator=23
COLON=9
StringLiteral=29
WS=42
UnicodeEscape=40
FloatingPointLiteral=27
MulOperator=26
EscapeSequence=39
OctalEscape=41
BooleanLiteral=30</pre><br /><br />当我知道期望的token类型的名字时，上面的tokens文件可以帮我找到对应的数值常量；但当我在Eclipse里调试时，看到的只有"type"，也就是token类型对应的数值常量，要找对应的名字就比较麻烦了。上上下下看得眼花。<br /><br />于是我自然希望顺序能颠倒一下，数值常量在前，名字在后，并且按照数值常量的大小按升序排序。像这样：<br />Dolphin.tokens.txt:<br /><pre name="code" class="java">4=FUNCTION
5=Identifier
6=LPAREN
7=RPAREN
8=COMMA
9=COLON
10=TypeSpecifier
11=LBRACE
12=RBRACE
13=VAR
14=SEMICOLON
15=AssignmentOperator
16=IF
17=DO
18=WHILE
19=FOR
20=BREAK
21=CONTINUE
22=RETURN
23=AssignmentShorthandOperator
24=RelationalOperator
25=AddOperator
26=MulOperator
27=FloatingPointLiteral
28=CharacterLiteral
29=StringLiteral
30=BooleanLiteral
31=NullLiteral
32=HexLiteral
33=OctalLiteral
34=DecimalLiteral
35=HexDigit
36=IntegerTypeSuffix
37=Exponent
38=FloatTypeSuffix
39=EscapeSequence
40=UnicodeEscape
41=OctalEscape
42=WS
43=Comment
44=LineComment</pre><br /><br />这种苦力事情显然不值得开动笨重的Java或者C#，哦别提C++和C了。这个时候最能让我偷懒的办法就是最好的办法 XD<br /><br />于是写了这样的一段Ruby脚本：<br />reformat.rb:<br /><pre name="code" class="ruby">#!/usr/bin/env ruby
# reformat.rb

## Reformat a token file produced by ANTLR to the format:
## token_number=token_name

def reformat( infile, outfile )
  lines = Array.new
  
  File.open infile, "r" do |file|
    file.each do |line|
      lines &lt;&lt; "#{$2}=#{$1}" if line.chomp =~ /^([^=]+)=([0-9]+)$/
    end
  end
  
  # yeah, i know this is slow, but we're not
  # pushing for speed anyway
  lines = lines.sort_by do |line|
    line =~ /^[0-9]+/
    $&.to_i
  end
  
  File.open outfile, "w" do |file|
    lines.each { |line| file.puts line }
  end
end

if ARGV.size != 2
  puts "Usage: #{$0} [token file] [output file]"
  exit
end

infile, outfile = ARGV
reformat infile, outfile</pre><br /><br />好吧，这段代码一点也不美。要是能把读写文件放在同一个循环里，顺带能排序就好了。这段代码仅有的好处就是没花多少时间去写而且功能符合我的需要，以后还可以继续用。<br />Ruby才刚开始用，希望有高手能指点指点怎么改进一下这代码～～<br /><br /><span style="color: blue">（20080328更新：加入了下面的版本的代码。避免在传给sort_by的block中使用正则表达式。虽然在循环里用了to_i还是稍嫌不爽）<br />（20080329更新：发觉应该用Enumerable#grep的。也不用在sort_by的block里用to_i了。很好，更简洁了）<br />（20080626更新：File.open还是用带block的方式好。IO对象不关掉始终是不放心。另外，原本定义了一个类当作tuple用，想想其实没必要定义个类，直接用数组就够了）</span><br />reformat.rb:<br /><pre name="code" class="ruby">#!/usr/bin/env ruby
# reformat.rb

## Reformat a token file produced by ANTLR to the format:
## token_number=token_name

def reformat( infile, outfile )
  lines = []
  File.open infile, "r" do |file|
    file.grep /^([^=]+)=([0-9]+)$/ do |line|
      lines.push [ $1, $2.to_i ] # name, value = $1, $2
    end
  end
  lines = lines.sort_by { |pair| pair[1] }
  File.open outfile, "w" do |file|
    lines.each { |pair| file.puts "#{pair[1]}=#{pair[0]}" }
  end
end

if ARGV.size != 2
  puts "Usage: #{$0} [token file] [output file]"
  exit
end

infile, outfile = ARGV
reformat infile, outfile</pre><br /><br />====================================================================<br /><br />P.S. 当然这东西不用Ruby还有更快的实现方法，直接用UltraEdit就行。<br />首先确保UltraEdit的Advanced->Configuration->Search->Regular Expression Engine里，"Perl compatible Regular Expressions"打上了钩。（我不熟悉UE自己定义的Regex的规格，试了好几次都不行，放弃了，换回相对熟悉些的Perl系Regex）<br />然后Ctrl+R（或者Search->Replace），在Find What里输入<br /><pre name="code" class="java">^([^=]+)=([0-9]+)$</pre><br />在Replace With里输入<br /><pre name="code" class="java">\2=\1</pre><br />接着File->Sort->Advanced Sort/Options...，选Numeric Sort，完事。
          <br/>
          <span style="color:red;">
            <a href="http://thinkinginruby.group.javaeye.com/group/blog/176731#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 27 Mar 2008 13:40:30 +0800</pubDate>
        <link>http://thinkinginruby.group.javaeye.com/group/blog/176731</link>
        <guid>http://thinkinginruby.group.javaeye.com/group/blog/176731</guid>
      </item>
          <item>
        <title>netbeans6.0.1和jdk6u4发布，貌似已经解决ubuntu下锁死键盘的问题</title>
        <author>crazycode</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://crazycode.javaeye.com">crazycode</a>&nbsp;
                    链接：<a href="http://thinkinginruby.group.javaeye.com/group/blog/162144" style="color:red;">http://thinkinginruby.group.javaeye.com/group/blog/162144</a>&nbsp;
          发表时间: 2008年02月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          下载并在ubuntu7.10下安装，经简单测试，貌似已经解决了之前发现的多点几次鼠标就会锁死键盘的问题。见<a href="http://forum.ubuntu.org.cn/viewtopic.php?p=626412" target="_blank">http://forum.ubuntu.org.cn/viewtopic.php?p=626412</a><br />唉，可惜我现在使用emacs已经上瘾了。当初因为windows下ror的单元测试过慢，而切换到ubuntu下，而因为ubuntu下netbeans会出现键盘无反应，而下定决心学习emacs，现在emacs刚入门，netbeans的问题又已经解决了 ...orz...
          <br/>
          <span style="color:red;">
            <a href="http://thinkinginruby.group.javaeye.com/group/blog/162144#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 13 Feb 2008 23:16:34 +0800</pubDate>
        <link>http://thinkinginruby.group.javaeye.com/group/blog/162144</link>
        <guid>http://thinkinginruby.group.javaeye.com/group/blog/162144</guid>
      </item>
          <item>
        <title>Ruby中的Mixin</title>
        <author>老王</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://thinkinginruby.javaeye.com">老王</a>&nbsp;
                    链接：<a href="http://thinkinginruby.group.javaeye.com/group/blog/148967" style="color:red;">http://thinkinginruby.group.javaeye.com/group/blog/148967</a>&nbsp;
          发表时间: 2007年12月17日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          在Ruby中，我们可以把一个模块混入（Mixin）到对象中，从而达到类似多重继承的效果。<br />
<br />
下面举几个例子来仔细阐述一下这个问题：<br />
<br />
首先定义一个Module：<br />
<br />
<strong><font face="Courier New">module Foo<br />
&nbsp; def bar<br />
&nbsp;&nbsp;&nbsp; puts &quot;foo&quot;;<br />
&nbsp; end<br />
end</font></strong><br />
<br />
然后我们把这个模块混入到对象中去：<br />
<strong><br />
<font face="Courier New">class Demo<br />
&nbsp; include Foo<br />
end</font></strong> <br />
<br />
如上编码后，模块中的实例方法就会被混入到对象中：<br />
<br />
<strong><font face="Courier New">d=Demo.new<br />
d.bar</font></strong><br />
<br />
会输出foo字样。<br />
<br />
下面我们重新定义一下Demo类：<br />
<strong><font face="Courier New"><br />
class Demo<br />
&nbsp; extend Foo<br />
end</font></strong><br />
<br />
这个时候如果你得到的就是静态调用：<br />
<br />
<strong><font face="Courier New">Demo.bar</font></strong><br />
<br />
会输出foo字样。<br />
<br />
下面我们再来重新定义一下Demo类：<br />
<br />
<strong><font face="Courier New">class Demo<br />
&nbsp; def bar<br />
&nbsp;&nbsp;&nbsp; puts &quot;demo&quot;<br />
&nbsp; end<br />
end</font></strong><br />
<br />
然后使用extend方法调用：<br />
<br />
<strong><font face="Courier New">d=Demo.new<br />
d.extend(Foo)<br />
d.bar</font></strong><br />
<br />
会输出foo字样。<br />
<br />
下面我们再来重新定义一下Demo类：<br />
<br />
<strong><font face="Courier New">class Demo<br />
&nbsp; include Foo<br />
&nbsp; <br />
&nbsp; def bar<br />
&nbsp;&nbsp;&nbsp; puts &quot;demo&quot;<br />
&nbsp; end<br />
end</font></strong><br />
<br />
然后使用extend方法调用：<br />
<br />
<strong><font face="Courier New">d=Demo.new<br />
d.extend(Foo)<br />
d.bar</font></strong><br />
<br />
会输出demo字样。<br />
<br />
其中的味道，自己慢慢体会吧。
          <br/>
          <span style="color:red;">
            <a href="http://thinkinginruby.group.javaeye.com/group/blog/148967#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 17 Dec 2007 20:30:47 +0800</pubDate>
        <link>http://thinkinginruby.group.javaeye.com/group/blog/148967</link>
        <guid>http://thinkinginruby.group.javaeye.com/group/blog/148967</guid>
      </item>
          <item>
        <title>Windows平台编译安装Ruby On Rails</title>
        <author>crazycode</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://crazycode.javaeye.com">crazycode</a>&nbsp;
                    链接：<a href="http://thinkinginruby.group.javaeye.com/group/blog/148751" style="color:red;">http://thinkinginruby.group.javaeye.com/group/blog/148751</a>&nbsp;
          发表时间: 2007年12月16日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          一直使用官方网站下载的ruby 1.8.5二进制包，感觉在windows下速度一般，决定自己编译一下看有没有优化的空间<br /><br />我的机器是Thinkpad T43，配置PM1.73G 内存1G win2003。以下过程的前提是安装了VC6.0，并且需要确保存在以下命名：nmake、cl、lib、dumpbin。更高版本的VC我没有试过。<br /><br />1、下载最新的ruby源代码包<br />目前最新的源代码包是1.8.6p111（下载地址：<a href="ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.6-p111.tar.gz" target="_blank">ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.6-p111.tar.gz</a>），下载后解压到一个临时目录，假设为C:\temp\ruby-1.8.6-p111。<br /><br />2、调整优化ruby源代码参数<br /><span style="color: red">注：此步骤是参考一些优化文章加入的，为试验性质，目前我还没有进行压力测试，无法证明其有效性，建议跳过</span><br />修改gc.c文件：<br /><pre name="code" class="java">第60行：#define GC_MALLOC_LIMIT 8000000 （默认为200000）
第312行：#define HEAP_MIN_SLOTS 60000  （默认为10000）
第315行：#define FREE_MIN  40960 （默认为4096）</pre><br /><br />3、设置编译环境变量：<br />运行gem及rails需要ssl、zlib等扩展库支持，需要配置对应include及lib环境。<br />下载附件support.zip(<a href="http://www.javaeye.com/topics/download/361e3f7a-4903-4400-96d9-313d315f6889" target="_blank">http://www.javaeye.com/topics/download/361e3f7a-4903-4400-96d9-313d315f6889</a>)，把附件中文件的include及lib都解压到一个临时目录，假设分别为C:\temp\support\include及C:\temp\suport\lib。<br />打开命令行，执行： <br /><pre name="code" class="java">C:\Program Files\Microsoft Visual Studio\VC98\Bin\vcvars32.bat
set INCLUDE=%INCLUDE%;C:\temp\support\include
set LIB=%LIB%;C:\temp\support\lib</pre><br />不要关闭这个命令行窗口，以下编译过程将在此命令行窗口进行。<br /><br />4、编译Ruby并安装到目标路径：<br />按ruby编译安装说明，依次执行以下命令：<br /><pre name="code" class="java">cd \temp\ruby-1.8.6-p111
win32\configure.bat i686-mswin32
nmake
nmake rubyw.exe
nmake test</pre><br />执行完成后，即已经生成ruby可执行文件，需要安装到目标路径，假设为C:\opt\ruby-1.8.6，执行以下命令：<br /><pre name="code" class="java">nmake DESTDIR=C:\opt\ruby-1.8.6 install</pre><br />执行完成后，把C:\opt\ruby-1.8.6\bin加入到PATH变量，即完成了ruby的编译安装。<br /><br />5、安装gem<br />首先关闭掉之前编译的命令行，打开新的命令行窗口，执行以下命令确认已经在使用编译版本的ruby：<br /><pre name="code" class="java">ruby -v</pre><br />下载最新的gem(<a href="http://rubyforge.org/frs/?group_id=126" target="_blank">http://rubyforge.org/frs/?group_id=126</a>)，目前为0.9.5。解压到一个临时目录，假设为C:\temp\rubygems-0.9.5。执行：<br /><pre name="code" class="java">
cd C:\temp\rubygems-0.9.5
ruby setup.rb
</pre><br />最后确认一下已经是使用了最新的gem：<br /><pre name="code" class="java">gem -v</pre><br /><br />6、安装rails<br />安装rails就简单了，使用标准的gem安装，我目前项目文件中使用的是rails1.1.6和rails1.2.3，所以执行以下命令：<br /><pre name="code" class="java">
gem install rails -v 1.1.6
gem install rails -v 1.2.3
</pre><br /><br />经测试，ruby运行速度及启动单元测试的速度无明显改善，但也提供了一种手工编译安装的参考方法吧。<br />有兴趣的同学可以使用Intel C++编译器或更高版本的VC编译器试一下。
          <br/>
          <span style="color:red;">
            <a href="http://thinkinginruby.group.javaeye.com/group/blog/148751#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 16 Dec 2007 23:59:01 +0800</pubDate>
        <link>http://thinkinginruby.group.javaeye.com/group/blog/148751</link>
        <guid>http://thinkinginruby.group.javaeye.com/group/blog/148751</guid>
      </item>
          <item>
        <title>在Windows操作系统上搭建一个Ruby&amp;Rails的开发平台</title>
        <author>老王</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://thinkinginruby.javaeye.com">老王</a>&nbsp;
                    链接：<a href="http://thinkinginruby.group.javaeye.com/group/blog/147552" style="color:red;">http://thinkinginruby.group.javaeye.com/group/blog/147552</a>&nbsp;
          发表时间: 2007年12月11日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          在国内，大多数Rubyer使用Windows操作系统，所以今天就先看看如何在Windows操作系统上搭建一个Ruby&amp;Rails的开发平台。<br />
<br />
最简单的方式就是安装<a href="http://rubyforge.org/projects/instantrails/">InstantRails</a>，它集成了大部分你需要的东西，不过话说回来，Ruby&amp;Rails的安装已经非常简单的，所以，还是推荐你自己手动安装开发环境。<br />
<br />
首先安装<a href="http://www.ruby-lang.org">Ruby</a>，安装过程很简单，一路Next就OK了，并且环境变量也自动设置好了，很不错。要想查看你的ruby安装是否成功，可以简单测试一下，比如说在命令行输入ruby -v，查看一下版本。<br />
<br />
然后安装<a href="http://www.rubyonrails.org/">Rails</a>，安装过程更简单，只要gem install rails --include-dependencies就OK了。<br />
<br />
BTW：开发环境搭建好了，推荐使用<a href="http://www.netbeans.org/features/ruby/index.html">NetBeans</a>做Ruby IDE。
          <br/>
          <span style="color:red;">
            <a href="http://thinkinginruby.group.javaeye.com/group/blog/147552#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">Windows7在微软WinHEC 2008上揭开神秘面纱</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 11 Dec 2007 14:14:09 +0800</pubDate>
        <link>http://thinkinginruby.group.javaeye.com/group/blog/147552</link>
        <guid>http://thinkinginruby.group.javaeye.com/group/blog/147552</guid>
      </item>
      </channel>
</rss>