﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-庄周梦蝶，孰蝶是我，我是孰蝶？一梦至今，蝶我已难分-随笔分类-动态语言 &amp; rails</title><link>http://www.blogjava.net/killme2008/category/19799.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 21 May 2008 10:54:02 GMT</lastBuildDate><pubDate>Wed, 21 May 2008 10:54:02 GMT</pubDate><ttl>60</ttl><item><title>最近的工作</title><link>http://www.blogjava.net/killme2008/archive/2008/05/21/201865.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Wed, 21 May 2008 03:45:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/05/21/201865.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/201865.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/05/21/201865.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/201865.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/201865.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 转眼间，来广州快半年了，感觉还不错。广州如死鱼所说的那样，是个包容并且很有活力的城市，习惯了周末煲汤，去天河公园跑跑步，这生活还是挺舒适的，除了比较潮的天气。<br />
&nbsp;&nbsp;&nbsp; 最近跟公司闹了点不愉快，在转正时间上，其实不是多大的事，只是心里不舒服罢了，干起活来也没什么激情了，呵呵。当然，手头的工作咱还是要高效率地完成，做完两个游戏后，现在转到棋牌类，棋牌类游戏核心就两个算法：随机发牌和出牌判断。随机发牌算法，学习了云风的blog上提到的方法，感觉还可以接受；出牌规则判断，倒是没想象中的复杂，建立牌型的OO模型，一切都很简单了。另外一个发现，用jdk6跑jruby1.1.1，比用jdk5跑效率（包括内存和CPU）好上很多，例如我们一个游戏进程，在使用jdk5时，CPU稳定在15%，内存85M，而改用jdk6后，cpu降到了%5以下，内存也缩减到70多M。<br />
&nbsp;&nbsp;&nbsp; 搞完了之后，时间有点空闲，就想学点新东西，最后选择了Prolog。Yep，非常地有趣，真正的声明式编程语言。Prolog本质上就是两个东西：规则和事实，由事实和规则出发，Prolog的推理系统将回答你的查询（query）。有点类似现在流行中的规则引擎的概念，在对效率不是很考虑的场景中，嵌入一个Prolog引擎做规则引擎完全是可以的，java中有个tuProlog项目，可以关注一下。然后就是一直在读的sicp，延时求值模拟无穷级数实在是相当地cool，大开眼界。这两天一直在理解continuation这个概念，小有所得。一个表达式的求值可以分为两个阶段：&#8220;What to evaluate?&#8221;和&#8220;What to do with the value&#8221;，&#8220;What to do with the value&#8221;就是计算的Continuation。例如，scheme求值下列表达式：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(</span><span style="color: #0000ff;">null</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;x)&nbsp;(quote&nbsp;())&nbsp;(cdr&nbsp;x))</span></div>
先求值表达式(null? x)，(null? x)就是&#8220;What to evaluate&#8221;，当(null? x)求值后，需要根据这个值来决定是执行(quote ())还是(cdr x)，这个根据值来决定的过程就是Continuation。如果在每次函数调用时，同时传入当前的continuation，那么就完全可以不要堆栈。call/cc就提供了这样的一个语法糖，call/cc全称就是call-with-current-continuation，要求参数是一个过程，调用这个过程，并且向这个过程传入当前的continuation（一般称为k,kont，或者Ruby中一般是c,cont)，这就是call/cc为我们做的。call/cc是实现Continuation的方式之一，coroutine/fiber/yield也是实现continuation的方式。《The Scheme Programming Language》给出的轻量级进程机制的例子比较有趣：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">(define&nbsp;lwp</span><span style="color: #000000;">-</span><span style="color: #000000;">list&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">())</span><span style="color: #800000;"><br />
</span><span style="color: #000000;">(define&nbsp;(lwp&nbsp;thunk)<br />
&nbsp;&nbsp;(set!&nbsp;lwp</span><span style="color: #000000;">-</span><span style="color: #000000;">list&nbsp;(append&nbsp;lwp</span><span style="color: #000000;">-</span><span style="color: #000000;">list&nbsp;(list&nbsp;thunk))))<br />
(define&nbsp;start<br />
&nbsp;&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">()<br />
&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;((p&nbsp;(car&nbsp;lwp</span><span style="color: #000000;">-</span><span style="color: #000000;">list)))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(set!&nbsp;lwp</span><span style="color: #000000;">-</span><span style="color: #000000;">list&nbsp;(cdr&nbsp;lwp</span><span style="color: #000000;">-</span><span style="color: #000000;">list))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(p))))<br />
(define&nbsp;pause<br />
&nbsp;&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">()<br />
&nbsp;&nbsp;&nbsp;&nbsp;(callcc&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">(k)&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(lwp&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">&nbsp;()&nbsp;(k&nbsp;</span><span style="color: #008000;">#</span><span style="color: #008000;">f)))</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(start)))))<br />
(lwp&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">&nbsp;()&nbsp;(let&nbsp;f&nbsp;()&nbsp;(display&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">h</span><span style="color: #800000;">"</span><span style="color: #000000;">)&nbsp;(pause)&nbsp;(f))))<br />
(lwp&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">&nbsp;()&nbsp;(let&nbsp;f&nbsp;()&nbsp;(display&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">e</span><span style="color: #800000;">"</span><span style="color: #000000;">)&nbsp;(pause)&nbsp;(f))))<br />
(lwp&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">&nbsp;()&nbsp;(let&nbsp;f&nbsp;()&nbsp;(display&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">y</span><span style="color: #800000;">"</span><span style="color: #000000;">)&nbsp;(pause)&nbsp;(f))))<br />
(lwp&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">&nbsp;()&nbsp;(let&nbsp;f&nbsp;()&nbsp;(display&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">!</span><span style="color: #800000;">"</span><span style="color: #000000;">)&nbsp;(pause)&nbsp;(f))))<br />
(lwp&nbsp;(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">&nbsp;()&nbsp;(let&nbsp;f&nbsp;()&nbsp;(newline)&nbsp;(pause)&nbsp;(f))))<br />
(start)</span></div>
实现了代码级的进程调度。<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/201865.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-05-21 11:45 <a href="http://www.blogjava.net/killme2008/archive/2008/05/21/201865.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ruby中实现stream</title><link>http://www.blogjava.net/killme2008/archive/2008/05/08/199367.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Thu, 08 May 2008 14:32:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/05/08/199367.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/199367.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/05/08/199367.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/199367.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/199367.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 流是通过延时求值实现的，Ruby中实现stream也是可以做到，可惜就是没有尾递归优化。按照sicp，首要的是两个函数：delay和force：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;mem_proc(exp)<br />
&nbsp;&nbsp;alread_run</span><span style="color: #000000;">=</span><span style="color: #000000;">false<br />
&nbsp;&nbsp;result</span><span style="color: #000000;">=</span><span style="color: #000000;">false<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;!alread_run<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result</span><span style="color: #000000;">=</span><span style="color: #000000;">exp.call<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alread_run</span><span style="color: #000000;">=</span><span style="color: #000000;">true<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;}<br />
end<br />
</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;force(delayed_object)<br />
&nbsp;&nbsp;delayed_object.call<br />
end<br />
</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;delay(exp)<br />
&nbsp;&nbsp;mem_proc(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">{exp})<br />
end</span></div>
&nbsp;&nbsp;&nbsp; delay函数返回延时对象，就是对于未来某个时间求值表达式的承诺；force函数以延时对象为参数，进行相应的求值工作，这里的mem_proc用于记忆已经求值过的表达式。定义stream的constructor和selector函数：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;cons_stream(a,b)<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;a,delay(b)<br />
end<br />
</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;stream_car(s)<br />
&nbsp;&nbsp;s[0]<br />
end<br />
</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;stream_cdr(s)<br />
&nbsp;&nbsp;force(s[</span><span style="color: #000000;">1</span><span style="color: #000000;">])<br />
end<br />
</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;stream_null?(s)<br />
&nbsp;&nbsp;s.nil?&nbsp;</span><span style="color: #0000ff;">or</span><span style="color: #000000;">&nbsp;s</span><span style="color: #000000;">==</span><span style="color: #000000;">[]<br />
end</span></div>
&nbsp;&nbsp;&nbsp; 用Ruby中的数组充当&#8220;粘合剂&#8221;，stream_car直接返回第一个元素，而stream_cdr需要用force求值表达式，履行承诺。另外，将空数组[]作为the-empty-stream。再定义几个高阶函数，map和foreach，其他如filter与此类似：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;stream_enumerate_interval(low,high)<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;low</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">high<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;[]<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;cons_stream(low,stream_enumerate_interval(low.succ,high))&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;end<br />
end<br />
</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;stream_ref(s,n)<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;n</span><span style="color: #000000;">==</span><span style="color: #000000;">0<br />
&nbsp;&nbsp;&nbsp;&nbsp;stream_car(s)<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;stream_ref(stream_cdr(s),(n</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">))&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;end<br />
end<br />
</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;stream_map(proc,s)<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;stream_null?(s)<br />
&nbsp;&nbsp;&nbsp;&nbsp;[]<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;cons_stream(proc.call(stream_car(s)),stream_map(proc,(stream_cdr(s))))&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;end<br />
end<br />
</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;stream_for_each(proc,s)<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;stream_null?(s)<br />
&nbsp;&nbsp;&nbsp;&nbsp;:done<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;proc.call(stream_car(s))<br />
&nbsp;&nbsp;&nbsp;&nbsp;stream_for_each(proc,stream_cdr(s))&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;end<br />
end<br />
</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;display_stream(s)<br />
&nbsp;&nbsp;stream_for_each(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">{</span><span style="color: #000000;">|</span><span style="color: #000000;">item</span><span style="color: #000000;">|</span><span style="color: #000000;">&nbsp;puts&nbsp;item},s)<br />
end<br />
</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;stream_filter(pred,s)<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;stream_null?(s)<br />
&nbsp;&nbsp;&nbsp;&nbsp;[]<br />
&nbsp;&nbsp;elsif&nbsp;pred.call(stream_car(s))<br />
&nbsp;&nbsp;&nbsp;&nbsp;cons_stream(stream_car(s),stream_filter(pred,stream_cdr(s)))<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;stream_filter(pred,stream_cdr(s))&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;end<br />
end</span></div>
<br />
&nbsp;&nbsp;&nbsp; 最后，看下例子：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">puts&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">s:</span><span style="color: #800000;">"</span><span style="color: #000000;"><br />
s</span><span style="color: #000000;">=</span><span style="color: #000000;">stream_enumerate_interval(</span><span style="color: #000000;">1</span><span style="color: #000000;">,</span><span style="color: #000000;">5</span><span style="color: #000000;">)<br />
display_stream(s)<br />
puts&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">odd_s:</span><span style="color: #800000;">"</span><span style="color: #000000;"><br />
odd_s</span><span style="color: #000000;">=</span><span style="color: #000000;">stream_filter(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">{</span><span style="color: #000000;">|</span><span style="color: #000000;">x</span><span style="color: #000000;">|</span><span style="color: #000000;">&nbsp;x</span><span style="color: #000000;">%</span><span style="color: #000000;">2</span><span style="color: #000000;">==</span><span style="color: #000000;">1</span><span style="color: #000000;">},s)<br />
display_stream(odd_s)<br />
puts&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">ss:</span><span style="color: #800000;">"</span><span style="color: #000000;"><br />
ss</span><span style="color: #000000;">=</span><span style="color: #000000;">stream_map(</span><span style="color: #0000ff;">lambda</span><span style="color: #000000;">{</span><span style="color: #000000;">|</span><span style="color: #000000;">x</span><span style="color: #000000;">|</span><span style="color: #000000;">x</span><span style="color: #000000;">*</span><span style="color: #000000;">x},s)<br />
display_stream(ss)</span></div>
<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/199367.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-05-08 22:32 <a href="http://www.blogjava.net/killme2008/archive/2008/05/08/199367.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Rope来高效处理长字符串</title><link>http://www.blogjava.net/killme2008/archive/2008/05/05/198532.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Mon, 05 May 2008 10:41:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/05/05/198532.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/198532.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/05/05/198532.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/198532.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/198532.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 前段时间看了这篇文章《<a href="http://www.ibm.com/developerworks/cn/java/j-ropes/index.html">Ropes：理论与实践</a>》。这两天为了提高工作中某个系统对外接口的效率，才认真学习了一番。本质上Ropes是将字符串表示为一棵二叉树，特别适用于长字符串的处理，貌似c++ STL库中也有这么个实现。具体实现和原理还是看这篇<a href="http://www.cs.ubc.ca/local/reading/proceedings/spe91-95/spe/vol25/issue12/spe986.pdf">paper</a>。《<a href="http://www.ibm.com/developerworks/cn/java/j-ropes/index.html">Ropes：理论与实践</a>》一文中给出的测试数据相当惊人，Ropes比之String和StringBuffer在append,insert,delete等操作上的效率都有一个数量级以上的差距。跑下作者给出的测试程序，其实在测试的字符串不是很长的情况下，这个差距并没有那么大，这也从侧面说明了Rope的应用范围：即只有在大量修改大型字符串的应用程序中才能看到明显的性能提升。那么是否可以用Rope替代StringBuffer做append生成字符串（比如我要的生成xml)。作者也说啦：<br />
&nbsp; &#8220;由于 <code>Rope</code> 的附加性能通常比 <code>StringBuffer</code> 好，这时使用 rope
是否有意义呢？答案还是否。不论何时将输入的数据组合在一起形成格式化输出时，最漂亮最有效的方法是使用模板引擎（例如 StringTemplate
或 FreeMarker）。这种方法不仅能干净地将表示标记与代码分开，而且模板只进行一次编译（通常编译为 JVM
字节码），以后可以重用，从而使它们拥有极佳的性能特征。&#8221;<br />
<br />
&nbsp;&nbsp;&nbsp; 我用Rope for java替代了StringBuffer做XML生成，效率提升在5%-30%左右，xml字符串不是很长，这个提升显然有限，也带来了不必要的复杂度。因此最后还是用Velocity模板引擎来生成XML，测试的结果效率并没有多少改善，但是显然更容易维护和开发了。回到Rope的话题，我用Ruby实现了个版本，Rubyforge上有一个Rope的实现，但是看了源码，与paper所述算法有点差异，因此照着Rope for java也实现了一个<a href="http://code.google.com/p/rope4r/">Rope4r</a>。测试的结果证明在长字符串的累积操作上，Rope4r的append比之String的+=性能可以快上3倍左右，而如果采用String的&lt;&lt;操作，不是immutable的，当然是最快了；比较郁闷的是slice和insert操作都比String的慢上几倍，因为Ruby的String、Array的内建对象都是直接用c写成并做了优化的，我猜测原因在这。<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/198532.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-05-05 18:41 <a href="http://www.blogjava.net/killme2008/archive/2008/05/05/198532.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>善用表驱动法</title><link>http://www.blogjava.net/killme2008/archive/2008/04/17/193852.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Thu, 17 Apr 2008 11:50:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/04/17/193852.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/193852.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/04/17/193852.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/193852.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/193852.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 最近碰到个需求，计算游戏得分的规则，类似这样：<br />
<table class="MsoNormalTable" style="border: medium none ; border-collapse: collapse;" border="1" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td style="padding: 0cm 5.4pt; background: #dfdfdf none repeat scroll 0%; width: 85.2pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;" valign="top" width="114">
            <p class="MsoNormal"><span style="font-family: 宋体; color: red;">游戏人数</span><span style="color: red;" lang="EN-US"><o:p></o:p></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; background: #dfdfdf none repeat scroll 0%; width: 85.2pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;" valign="top" width="114">
            <p class="MsoNormal"><span style="font-family: 宋体; color: red;">第一名获得赌注</span><span style="color: red;" lang="EN-US"><o:p></o:p></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; background: #dfdfdf none repeat scroll 0%; width: 85.2pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;" valign="top" width="114">
            <p class="MsoNormal"><span style="font-family: 宋体; color: red;">第二名获得赌注</span><span style="color: red;" lang="EN-US"><o:p></o:p></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; background: #dfdfdf none repeat scroll 0%; width: 85.25pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;" valign="top" width="114">
            <p class="MsoNormal"><span style="font-family: 宋体; color: red;">第三名获得赌注</span><span style="color: red;" lang="EN-US"><o:p></o:p></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; background: #dfdfdf none repeat scroll 0%; width: 85.25pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;" valign="top" width="114">
            <p class="MsoNormal"><span style="font-family: 宋体; color: red;">第四名获得赌注</span><span style="color: red;" lang="EN-US"><o:p></o:p></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 0cm 5.4pt; width: 85.2pt;" valign="top" width="114">
            <p class="MsoNormal"><strong><span style="font-family: 宋体; color: red;">二人</span><span style="color: red;" lang="EN-US"><o:p></o:p></span></strong></p>
            </td>
            <td style="padding: 0cm 5.4pt; width: 85.2pt;" valign="top" width="114">
            <p class="MsoNormal" style="text-align: center;" align="center"><span style="color: red;" lang="EN-US">100%<o:p></o:p></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; width: 85.2pt;" valign="top" width="114">
            <p class="MsoNormal" style="text-align: center;" align="center"><span style="color: red;" lang="EN-US">0%<o:p></o:p></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; background: #b4b4b4 none repeat scroll 0%; width: 85.25pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;" valign="top" width="114">
            <p class="MsoNormal" style="text-align: center;" align="center"><span style="font-family: 宋体; color: red;">—</span><span style="color: red;" lang="EN-US"><o:p></o:p></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; background: #b4b4b4 none repeat scroll 0%; width: 85.25pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;" valign="top" width="114">
            <p class="MsoNormal" style="text-align: center;" align="center"><span style="font-family: 宋体; color: red;">—</span><span style="color: red;" lang="EN-US"><o:p></o:p></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 0cm 5.4pt; width: 85.2pt;" valign="top" width="114">
            <p class="MsoNormal"><strong><span style="font-family: 宋体; color: red;">二人</span></strong><span style="font-size: 9pt; font-family: 宋体; color: red;">（出现</span><span style="font-size: 9pt; color: red;" lang="EN-US">2</span><span style="font-size: 9pt; font-family: 宋体; color: red;">个第</span><span style="font-size: 9pt; color: red;" lang="EN-US">1</span><span style="font-size: 9pt; font-family: 宋体; color: red;">名时）</span><strong><span style="color: red;" lang="EN-US"><o:p></o:p></span></strong></p>
            </td>
            <td style="padding: 0cm 5.4pt; width: 85.2pt;" valign="top" width="114">
            <p class="MsoNormal" style="text-align: center;" align="center"><span style="color: red;" lang="EN-US">50%<o:p></o:p></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; width: 85.2pt;" valign="top" width="114">
            <p class="MsoNormal" style="text-align: center;" align="center"><span style="color: red;" lang="EN-US">50%<o:p></o:p></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; background: #b4b4b4 none repeat scroll 0%; width: 85.25pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;" valign="top" width="114">
            <p class="MsoNormal" style="text-align: center;" align="center"><span style="color: red;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; background: #b4b4b4 none repeat scroll 0%; width: 85.25pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;" valign="top" width="114">
            <p class="MsoNormal" style="text-align: center;" align="center"><span style="color: red;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 0cm 5.4pt; width: 85.2pt;" valign="top" width="114">
            <p class="MsoNormal"><strong><span style="font-family: 宋体; color: red;">三人</span><span style="color: red;" lang="EN-US"><o:p></o:p></span></strong></p>
            </td>
            <td style="padding: 0cm 5.4pt; width: 85.2pt;" valign="top" width="114">
            <p class="MsoNormal" style="text-align: center;" align="center"><span style="color: red;" lang="EN-US">70%<o:p></o:p></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; width: 85.2pt;" valign="top" width="114">
            <p class="MsoNormal" style="text-align: center;" align="center"><span style="color: red;" lang="EN-US">30%<o:p></o:p></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; width: 85.25pt;" valign="top" width="114">
            <p class="MsoNormal" style="text-align: center;" align="center"><span style="color: red;" lang="EN-US">0%<o:p></o:p></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; background: #b4b4b4 none repeat scroll 0%; width: 85.25pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;" valign="top" width="114">
            <p class="MsoNormal" style="text-align: center;" align="center"><span style="font-family: 宋体; color: red;">—</span><span style="color: red;" lang="EN-US"><o:p></o:p></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 0cm 5.4pt; width: 85.2pt;" valign="top" width="114">
            <p class="MsoNormal"><strong><span style="font-family: 宋体; color: red;">三人</span></strong><span style="font-family: 宋体; color: red;">（</span><span style="font-size: 9pt; font-family: 宋体; color: red;">出现</span><span style="font-size: 9pt; color: red;" lang="EN-US">3</span><span style="font-size: 9pt; font-family: 宋体; color: red;">个第</span><span style="font-size: 9pt; color: red;" lang="EN-US">1</span><span style="font-size: 9pt; font-family: 宋体; color: red;">名时</span><span style="font-family: 宋体; color: red;">）</span><span style="color: red;" lang="EN-US"><o:p></o:p></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; width: 85.2pt;" valign="top" width="114">
            <p class="MsoNormal" style="text-align: center;" align="center"><span style="color: red;" lang="EN-US">33.3333%<o:p></o:p></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; width: 85.2pt;" valign="top" width="114">
            <p class="MsoNormal" style="text-align: center;" align="center"><span style="color: red;" lang="EN-US">33.3333%<o:p></o:p></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; width: 85.25pt;" valign="top" width="114">
            <p class="MsoNormal" style="text-align: center;" align="center"><span style="color: red;" lang="EN-US">33.3333%<o:p></o:p></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; background: #b4b4b4 none repeat scroll 0%; width: 85.25pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;" valign="top" width="114">
            <p class="MsoNormal" style="text-align: center;" align="center"><span style="color: red;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 0cm 5.4pt; width: 85.2pt;" valign="top" width="114">
            <p class="MsoNormal"><strong><span style="font-family: 宋体; color: red;">三人</span></strong><span style="font-size: 9pt; color: red;" lang="EN-US">(</span><span style="font-size: 9pt; font-family: 宋体; color: red;">出现</span><span style="font-size: 9pt; color: red;" lang="EN-US">2</span><span style="font-size: 9pt; font-family: 宋体; color: red;">个第</span><span style="font-size: 9pt; color: red;" lang="EN-US">1</span><span style="font-size: 9pt; font-family: 宋体; color: red;">名时</span><span style="font-size: 9pt; color: red;" lang="EN-US">)</span><span style="color: red;" lang="EN-US"><o:p></o:p></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; width: 85.2pt;" valign="top" width="114">
            <p class="MsoNormal" style="text-align: center;" align="center"><span style="color: red;" lang="EN-US">50%</span><span style="font-family: 宋体; color: red;">&#215;</span><span style="color: red;" lang="EN-US">2<o:p></o:p></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; width: 85.2pt;" valign="top" width="114">
            <p class="MsoNormal" style="text-align: center;" align="center"><span style="color: red;" lang="EN-US">0%<o:p></o:p></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; background: #b4b4b4 none repeat scroll 0%; width: 85.25pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;" valign="top" width="114">
            <p class="MsoNormal" style="text-align: center;" align="center"><span style="color: red;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
            </td>
            <td style="padding: 0cm 5.4pt; background: #b4b4b4 none repeat scroll 0%; width: 85.25pt; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;" valign="top" width="114">
            <p class="MsoNormal" style="text-align: center;" align="center"><span style="color: red;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
            </td>
        </tr>
    </tbody>
</table>
......<br />
......<br />
&nbsp;&nbsp;&nbsp; 这些奖励规则没有什么规律，随着人数增多，就越发复杂了，并且业务人员可能随时改变这些规则。<br />
&nbsp;&nbsp;&nbsp; 显然，奖励规则可以采用策略模式，定义策略接口，根据游戏人数定义不同的规则，本质上就是利用动态的多态调用。可以想见，还是少不了复杂的case...when语句，以及繁多的代码。恰好最近读《unix编程艺术》和《代码大全2》，两者都提到一个结论：人类阅读复杂数据结构远比复杂的控制流程容易，或者说数据驱动开发是非常有价值的。《代码大全2》声称这个是表驱动法。因此，这个奖励系数的计算，能否转化成一个查表过程呢？注意到，在游戏中，名次是根据个人的积分在所有玩家中的排位来决定，大概会有这么个排序的玩家积分数组[100,50,3]，这个数组表示3个玩家，第一名100分，第二名50分，第三名才3分。依据规则，第一名的奖励系数就是0.7，第二名就是0.3。我想到类似这样的数组其实都有个形式表示它们的内置结构，比如[100,50,3]数组的&#8220;结构&#8221;是"111"，代表3个位置都有一个人。将"111"作为关键码去查表不就OK了？<br />
&nbsp;&nbsp;&nbsp; 将每个排好序的积分数组解码为这样的关键码，然后去查预先写好的奖励系数表，这个奖励系数表大概类似：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">&nbsp;&nbsp;@@award_rate_hash</span><span style="color: #000000;">=</span><span style="color: #000000;">{<br />
&nbsp;&nbsp;&nbsp;&nbsp;:</span><span style="color: #800000;">"</span><span style="color: #800000;">2</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:</span><span style="color: #800000;">"</span><span style="color: #800000;">11</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">{:</span><span style="color: #800000;">"</span><span style="color: #800000;">1</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">1</span><span style="color: #000000;">,:</span><span style="color: #800000;">"</span><span style="color: #800000;">2</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:</span><span style="color: #800000;">"</span><span style="color: #800000;">20</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">{:</span><span style="color: #800000;">"</span><span style="color: #800000;">1</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0.5</span><span style="color: #000000;">,:</span><span style="color: #800000;">"</span><span style="color: #800000;">2</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0.5</span><span style="color: #000000;">}<br />
&nbsp;&nbsp;&nbsp;&nbsp;},<br />
&nbsp;&nbsp;&nbsp;&nbsp;:</span><span style="color: #800000;">"</span><span style="color: #800000;">3</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:</span><span style="color: #800000;">"</span><span style="color: #800000;">111</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">{:</span><span style="color: #800000;">"</span><span style="color: #800000;">1</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0.7</span><span style="color: #000000;">,:</span><span style="color: #800000;">"</span><span style="color: #800000;">2</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0.3</span><span style="color: #000000;">,:</span><span style="color: #800000;">"</span><span style="color: #800000;">3</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:</span><span style="color: #800000;">"</span><span style="color: #800000;">300</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">{:</span><span style="color: #800000;">"</span><span style="color: #800000;">1</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0.33</span><span style="color: #000000;">},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:</span><span style="color: #800000;">"</span><span style="color: #800000;">201</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">{:</span><span style="color: #800000;">"</span><span style="color: #800000;">1</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0.5</span><span style="color: #000000;">,:</span><span style="color: #800000;">"</span><span style="color: #800000;">3</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:</span><span style="color: #800000;">"</span><span style="color: #800000;">120</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">{:</span><span style="color: #800000;">"</span><span style="color: #800000;">1</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">1</span><span style="color: #000000;">,:</span><span style="color: #800000;">"</span><span style="color: #800000;">2</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0}<br />
&nbsp;&nbsp;&nbsp;&nbsp;},<br />
&nbsp;&nbsp;&nbsp;&nbsp;:</span><span style="color: #800000;">"</span><span style="color: #800000;">4</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:</span><span style="color: #800000;">"</span><span style="color: #800000;">1111</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">{:</span><span style="color: #800000;">"</span><span style="color: #800000;">1</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0.65</span><span style="color: #000000;">,:</span><span style="color: #800000;">"</span><span style="color: #800000;">2</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0.30</span><span style="color: #000000;">,:</span><span style="color: #800000;">"</span><span style="color: #800000;">3</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0.05</span><span style="color: #000000;">,:</span><span style="color: #800000;">"</span><span style="color: #800000;">4</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:</span><span style="color: #800000;">"</span><span style="color: #800000;">4000</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">{:</span><span style="color: #800000;">"</span><span style="color: #800000;">1</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0.25</span><span style="color: #000000;">},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:</span><span style="color: #800000;">"</span><span style="color: #800000;">3001</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">{:</span><span style="color: #800000;">"</span><span style="color: #800000;">1</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0.33</span><span style="color: #000000;">,:</span><span style="color: #800000;">"</span><span style="color: #800000;">4</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:</span><span style="color: #800000;">"</span><span style="color: #800000;">1300</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">{:</span><span style="color: #800000;">"</span><span style="color: #800000;">1</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">1</span><span style="color: #000000;">,:</span><span style="color: #800000;">"</span><span style="color: #800000;">2</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:</span><span style="color: #800000;">"</span><span style="color: #800000;">2020</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">{:</span><span style="color: #800000;">"</span><span style="color: #800000;">1</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0.5</span><span style="color: #000000;">,:</span><span style="color: #800000;">"</span><span style="color: #800000;">3</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:</span><span style="color: #800000;">"</span><span style="color: #800000;">1201</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">{:</span><span style="color: #800000;">"</span><span style="color: #800000;">1</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0.7</span><span style="color: #000000;">,:</span><span style="color: #800000;">"</span><span style="color: #800000;">2</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0.15</span><span style="color: #000000;">,:</span><span style="color: #800000;">"</span><span style="color: #800000;">4</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:</span><span style="color: #800000;">"</span><span style="color: #800000;">1120</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">{:</span><span style="color: #800000;">"</span><span style="color: #800000;">1</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0.7</span><span style="color: #000000;">,:</span><span style="color: #800000;">"</span><span style="color: #800000;">2</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0.3</span><span style="color: #000000;">,:</span><span style="color: #800000;">"</span><span style="color: #800000;">3</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:</span><span style="color: #800000;">"</span><span style="color: #800000;">2011</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">{:</span><span style="color: #800000;">"</span><span style="color: #800000;">1</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0.35</span><span style="color: #000000;">,:</span><span style="color: #800000;">"</span><span style="color: #800000;">3</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0.3</span><span style="color: #000000;">,:</span><span style="color: #800000;">"</span><span style="color: #800000;">4</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;}</span></div>
&nbsp;&nbsp;&nbsp; 一个三级hash表，首先根据玩家人数查到特定的系数表，比如要查3个玩家、积分数组是[100,50,3]的奖励系数表就是<span style="color: #000000;">&nbsp; @@award_rate_hash</span><span style="color: #000000;">[:"3"]，然后积分数组</span>[100,50,3]<span style="color: #000000;">解码为:"111"，继续查，如此规则的奖励系数表就是</span><span style="color: #000000;">@@award_rate_hash</span><span style="color: #000000;">[:"3"][</span><span style="color: #000000;">:"111"]——也就是</span><span style="color: #000000;"> </span><span style="color: #000000;">{:</span><span style="color: #800000;">"</span><span style="color: #800000;">1</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0.7</span><span style="color: #000000;">,:</span><span style="color: #800000;">"</span><span style="color: #800000;">2</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0.3</span><span style="color: #000000;">,:</span><span style="color: #800000;">"</span><span style="color: #800000;">3</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0}，那么查积分是100的玩家系数就是</span><span style="color: #000000;">@@award_rate_hash</span><span style="color: #000000;">[:"3"][</span><span style="color: #000000;">:"111"][</span>([100,50,3].index(100)+1<span style="color: #000000;">).to_s.to_sym]，也就是</span><span style="color: #000000;">:</span><span style="color: #800000;">"</span><span style="color: #800000;">1</span><span style="color: #800000;">"</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">0.7</span><span style="color: #000000;">。</span>[100,50,3].index(100)+1<span style="color: #000000;">就是积分100的玩家在数组中的名次(即1)，也就是:"1"指向的结果0.7</span>。其他玩家的查表过程与此类似，不细说了。<br />
&nbsp;&nbsp;&nbsp; 这样，我们所有的奖励规则就是维护这么一张hash表，这个表看起来复杂，其实完全可以自动生成，让业务人员来提供样例数据，解码样例数据并生成这个表是很简单的事情。积分数组的&#8220;解码&#8221;，我给一个Ruby版本：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">#</span><span style="color: #008000;">解码数组为字符串关键码</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;</span><span style="color: #0000ff;">def</span><span style="color: #000000;"> decode_array(array)<br />
&nbsp;&nbsp;&nbsp;&nbsp;len</span><span style="color: #000000;">=</span><span style="color: #000000;">array.size<br />
&nbsp;&nbsp;&nbsp;&nbsp;trace_list</span><span style="color: #000000;">=</span><span style="color: #000000;">[]<br />
&nbsp;&nbsp;&nbsp;&nbsp;result</span><span style="color: #000000;">=</span><span style="color: #000000;">[]<br />
&nbsp;&nbsp;&nbsp;&nbsp;len.times&nbsp;do&nbsp;</span><span style="color: #000000;">|</span><span style="color: #000000;">time</span><span style="color: #000000;">|</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result[time]</span><span style="color: #000000;">=</span><span style="color: #000000;">0&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;trace_list[time]</span><span style="color: #000000;">=</span><span style="color: #000000;">false<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;array.each_with_index&nbsp;do&nbsp;</span><span style="color: #000000;">|</span><span style="color: #000000;">item,index</span><span style="color: #000000;">|</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result[index]</span><span style="color: #000000;">=</span><span style="color: #000000;">count_times(array,trace_list,index,len)<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;result.join(</span><span style="color: #800000;">''</span><span style="color: #000000;">).to_sym<br />
&nbsp;&nbsp;end<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">def</span><span style="color: #000000;"> count_times(array,trace_list,index,len)<br />
&nbsp;&nbsp;&nbsp;&nbsp;item</span><span style="color: #000000;">=</span><span style="color: #000000;">array[index]<br />
&nbsp;&nbsp;&nbsp;&nbsp;result</span><span style="color: #000000;">=</span><span style="color: #000000;">0<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(index..len).each&nbsp;do&nbsp;</span><span style="color: #000000;">|</span><span style="color: #000000;">i</span><span style="color: #000000;">|</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;array[i]</span><span style="color: #000000;">==</span><span style="color: #000000;">item&nbsp;</span><span style="color: #0000ff;">and</span><span style="color: #000000;">&nbsp;!trace_list[i]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result</span><span style="color: #000000;">+=</span><span style="color: #000000;">1</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;trace_list[i]</span><span style="color: #000000;">=</span><span style="color: #000000;">true<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;result<br />
&nbsp;&nbsp;end</span></div>
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/193852.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-04-17 19:50 <a href="http://www.blogjava.net/killme2008/archive/2008/04/17/193852.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>lua 5.0的实现（翻译)4,5</title><link>http://www.blogjava.net/killme2008/archive/2008/04/07/191324.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Mon, 07 Apr 2008 09:55:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/04/07/191324.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/191324.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/04/07/191324.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/191324.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/191324.html</trackback:ping><description><![CDATA[<p class="MsoNormal" style="text-align: left;" align="left"><strong><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">4</span><span style="font-size: 9pt; font-family: 宋体;">、</span><span style="font-size: 9pt; font-family: CMR9;"> </span><span style="font-size: 9pt; font-family: 宋体;">表</span></strong><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span>Table</span><span style="font-size: 9pt; font-family: 宋体;">是</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">的主要——实际上，也是唯一的——数据结构。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Table</span><span style="font-size: 9pt; font-family: 宋体;">不仅在语言中，同时也在语言的实现中扮演着重要角色。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Effort spent on a good implementation of tables is
rewarded in the language,because tables are used
for several internal tasks, with no qualms about performance</span><span style="font-size: 10pt; font-family: 宋体;">。这有助于保持实现的小巧。相反的，</span><span style="font-family: 宋体;">任何其他数据结构的机制的缺乏也为</span><span lang="EN-US">table</span><span style="font-family: 宋体;">的高效实现带来了很大压力</span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Lua</span><span style="font-family: 宋体;">中的</span><span lang="EN-US">table</span><span style="font-family: 宋体;">是关联数组，也就是可以用任何值做索引（除了</span><span lang="EN-US">nil</span><span style="font-family: 宋体;">），也可以持有任何值。另外，</span><span lang="EN-US">table</span><span style="font-family: 宋体;">是动态的，也就是说当加进数据的时候它们将增长（给迄今不存在的域赋值）而移除数据的时候将萎缩（给域赋</span><span lang="EN-US">nil</span><span style="font-family: 宋体;">值）。</span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 21.75pt;" align="left"><span style="font-family: 宋体;">不像大多数其他脚本语言，</span><span lang="EN-US">lua</span><span style="font-family: 宋体;">没有数组类型。数组被表示为以整数做键的</span><span lang="EN-US">table</span><span style="font-family: 宋体;">。用</span><span lang="EN-US">table</span><span style="font-family: 宋体;">作为数组对于语言是有益的。主要的（益处）显而易见：</span><span lang="EN-US">lua</span><span style="font-family: 宋体;">并不需要操纵表和数组的两套不同的运算符。另外，程序员不用对两种实现做出艰难选择。在</span><span lang="EN-US">lua</span><span style="font-family: 宋体;">中实现稀疏数组是轻而易举的。例如，在</span><span lang="EN-US">Perl</span><span style="font-family: 宋体;">里面，如果你尝试去跑</span><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">$a[1000000000]=1 </span><span style="font-size: 10pt; font-family: 宋体;">这样的程序，你能跑出个内存溢出！（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">you can run out of memory</span><span style="font-size: 10pt; font-family: 宋体;">），因为它触发了一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">10</span><span style="font-size: 10pt; font-family: 宋体;">亿个元素的数组的创建（译注，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Perl</span><span style="font-size: 10pt; font-family: 宋体;">的哲学是：去除不必要的限制）。而等价的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">程序</span><span style="font-size: 10pt; font-family: CMR10;"> </span><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">a={[1000000000]=1}</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">,</span><span style="font-size: 10pt; font-family: 宋体;">（只是）创建了有一个单独的项的表（而已）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<img src="http://www.blogjava.net/images/blogjava_net/killme2008/lua01.jpg" alt="" border="0" /><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><!--[if gte vml 1]><v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">
<v:stroke joinstyle="miter" />
<v:formulas>
<v:f eqn="if lineDrawn pixelLineWidth 0" />
<v:f eqn="sum @0 1 0" />
<v:f eqn="sum 0 0 @1" />
<v:f eqn="prod @2 1 2" />
<v:f eqn="prod @3 21600 pixelWidth" />
<v:f eqn="prod @3 21600 pixelHeight" />
<v:f eqn="sum @0 0 1" />
<v:f eqn="prod @6 1 2" />
<v:f eqn="prod @7 21600 pixelWidth" />
<v:f eqn="sum @8 21600 0" />
<v:f eqn="prod @7 21600 pixelHeight" />
<v:f eqn="sum @10 21600 0" />
</v:formulas>
<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect" />
<o:lock v:ext="edit" aspectratio="t" />
</v:shapetype><v:shape id="_x0000_i1025" type="#_x0000_t75" style='width:414.75pt;
height:198pt'>
<v:imagedata src="file:///C:\DOCUME~1\cy\LOCALS~1\Temp\msohtml1\08\clip_image001.gif" o:title="2007-12-04_152712" />
</v:shape><![endif]--><!--[if !vml]--><br />
<!--[endif]--><o:p></o:p></span>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 9pt; font-family: 宋体;">直到</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua 4.0</span><span style="font-size: 9pt; font-family: 宋体;">，</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">table</span><span style="font-size: 9pt; font-family: 宋体;">都是作为</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">hash</span><span style="font-size: 9pt; font-family: 宋体;">表严格地实现：所有的</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">pair</span><span style="font-size: 9pt; font-family: 宋体;">都被显式地保存。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua5.0</span><span style="font-size: 9pt; font-family: 宋体;">引入了一个新算法来优化作为数组的</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">table</span><span style="font-size: 9pt; font-family: 宋体;">：它将以整数为键的</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">pair</span><span style="font-size: 9pt; font-family: 宋体;">不再是存储键而是优化成存储值在真正的数组中。更精确地说，在</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua 5.0</span><span style="font-size: 9pt; font-family: 宋体;">中，</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">table</span><span style="font-size: 9pt; font-family: 宋体;">被实现为一个混合数据结构：它们包括一个</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">hash</span><span style="font-size: 9pt; font-family: 宋体;">部分和一个数组部分。图</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">2</span><span style="font-size: 9pt; font-family: 宋体;">展示了一个有</span><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">"x"</span><span style="font-size: 10pt; font-family: 宋体;">&#8594;</span><span style="font-size: 10pt; font-family: CMSY10;"> </span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">9.3, 1 </span><span style="font-size: 10pt; font-family: 宋体;">&#8594;</span><span style="font-size: 10pt; font-family: CMSY10;"> </span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">100,2 </span><span style="font-size: 10pt; font-family: 宋体;">&#8594;</span><span style="font-size: 10pt; font-family: CMSY10;"> </span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">200, 3 </span><span style="font-size: 10pt; font-family: 宋体;">&#8594;</span><span style="font-size: 10pt; font-family: CMSY10;"> </span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">300</span><span style="font-size: 10pt; font-family: 宋体;">对子的表的一种可能结构。注意到数组部分在右边，并没有存储整数的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">key</span><span style="font-size: 10pt; font-family: 宋体;">。这个划分仅仅是在一个低的实现层次进行的，访问</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">仍然是透明的，甚至在虚拟机内部（访问</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">）也是如此。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Table</span><span style="font-size: 10pt; font-family: 宋体;">根据内容自动并且动态地对两个部分进行适配：数组部分试图从</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">1</span><span style="font-size: 10pt; font-family: 宋体;">到</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">n</span><span style="font-size: 10pt; font-family: 宋体;">的相应地存储值，关联非整数键或者整数键超过数组范围的值被存储在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">部分。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">当一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">需要增长时，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">重新计算</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">部分和数组部分的大小。任一部分都可能是空的。重新计算后的数组大小是至少是当前使用的数组部分从</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">1</span><span style="font-size: 10pt; font-family: 宋体;">到</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">n</span><span style="font-size: 10pt; font-family: 宋体;">的一半情况下的最大</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">n</span><span style="font-size: 10pt; font-family: 宋体;">值（原文：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">The computed
size of the array part is the largest </span><span style="font-size: 10pt; font-family: CMMI10;" lang="EN-US">n </span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">such that at least half the slots between 1 and </span><span style="font-size: 10pt; font-family: CMMI10;" lang="EN-US">n </span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">are in use</span><span style="font-size: 10pt; font-family: 宋体;">）（稀疏数组时避免浪费空间），并至少有一个（元素）处在</span><span style="font-size: 10pt; font-family: CMMI10;" lang="EN-US">n/</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">2+1</span><span style="font-size: 10pt; font-family: 宋体;">到</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">n</span><span style="font-size: 10pt; font-family: 宋体;">的槽中（当</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">n</span><span style="font-size: 10pt; font-family: 宋体;">被</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">2</span><span style="font-size: 10pt; font-family: 宋体;">整除时，避免</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">n</span><span style="font-size: 10pt; font-family: 宋体;">的这样的数组大小）。计算完大小后，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">创建了&#8220;新&#8221;的部分并将&#8220;旧&#8221;的部分的元素重新插入到的&#8220;新&#8221;的部分。作为一个例子，假设</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">a</span><span style="font-size: 10pt; font-family: 宋体;">是一个空表；它的数组部分和</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">部分的大小都是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">0</span><span style="font-size: 10pt; font-family: 宋体;">。当我们执行</span><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">a[1]=v</span><span style="font-size: 10pt; font-family: 宋体;">时，这个表需要增长到足够容纳新的键。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">将为新的数组部分的大小选择</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">n=1</span><span style="font-size: 10pt; font-family: 宋体;">（带有一个项</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">1</span><span style="font-size: 10pt; font-family: 宋体;">&#8594;</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">v</span><span style="font-size: 10pt; font-family: 宋体;">）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">部分仍然保持为空。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">这个混合的方案有两个优点。首先，访问以整数为键的值加快了，因为不再需要任何的散列行为。其次，也是最重要的，数组部分占用的内存大概是将数组部分存储在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">部分时的一半，因为</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">key</span><span style="font-size: 10pt; font-family: 宋体;">在数组中是隐式的（译注：也就是数组的下标）而在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">部分却是显式的。因而，当一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">被用作数组的时，它表现的就像一个数组，只要整数键是密集。另外，不用为</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">部分付出任何内存和时间上的惩罚，因为它（译注：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">部分）甚至都不存在。相反的控制：如果</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">被用作关联数组而非一个数组，数组部分可能就是空的。这些内存上的节省是比较重要的，因为</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">程序经常创建一些小的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">，例如</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">被用来实现对象（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Object</span><span style="font-size: 10pt; font-family: 宋体;">）（译注，也就是用</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">来模仿对象，有点类似</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">javascript</span><span style="font-size: 10pt; font-family: 宋体;">中的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">json</span><span style="font-size: 10pt; font-family: 宋体;">）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Hash</span><span style="font-size: 10pt; font-family: 宋体;">部分采用</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Brent's
variation[3]</span><span style="font-size: 10pt; font-family: 宋体;">的组合的链状发散表。这些</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">的主要不变式是如果一个元素没有在它的主要位置上（也就是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">值的原始位置），则冲突的元素在它自己的主要位置上。换句话说，仅当两个元素有相同的主要位置（也就是在当时</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">大小情况下的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">值）时才有冲突的。没有二级冲突。正因为那样，这些</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">的加载因子可以是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">100%</span><span style="font-size: 10pt; font-family: 宋体;">而没有性能上的损失。这部分不是很明白，附上原文：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 20pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">The hash part uses a mix of chained scatter table with
Brent's variation [3].<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">A main invariant of
these tables is that if an element is not in its main position<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">(i.e., the original
position given by its hash value), then the colliding element<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">is in its own main
position. In other words, there are collisions only when two<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">elements have the same
main position (i.e., the same hash values for that table<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">size). There are no
secondary collisions. Because of that, the load factor of these<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">tables can be 100% without performance penalties.<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><strong><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></strong></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><strong><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">5</span></strong><strong><span style="font-size: 10pt; font-family: 宋体;">、函数和闭包</span></strong><strong><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></strong></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">当</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">编译一个函数的时候，它产生一个模型（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">prototype</span><span style="font-size: 10pt; font-family: 宋体;">），包括了函数的虚拟机指令、常量值（数字，字符串字面量等）和一些调试信息。运行的时候，无论何时</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">执行一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">function&#8230;end</span><span style="font-size: 10pt; font-family: 宋体;">表达式，它都创建一个新的闭包。每个闭包都有一个引用指向相应的模型，一个引用指向环境（</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">environment</span><span style="font-size: 10pt; font-family: 宋体;">）（一张查找全局变量的表，译注：指所谓环境就是这样一张表），和一组用来访问外部</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量的指向</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">的引用。</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US"><o:p></o:p></span></p>
<div style="border-style: none none solid; border-color: -moz-use-text-color -moz-use-text-color windowtext; border-width: medium medium 1pt; padding: 0cm 0cm 1pt;">
<p class="MsoNormal" style="border: medium none ; padding: 0cm; text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">词法范围以及</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">first-class</span><span style="font-size: 10pt; font-family: 宋体;">函数的组合导致一个关于（如何）访问外部</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量的著名难题。考虑图</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">3</span><span style="font-size: 10pt; font-family: 宋体;">中的例子。当</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add2</span><span style="font-size: 10pt; font-family: 宋体;">被调用的时候，它的函数体（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">body</span><span style="font-size: 10pt; font-family: 宋体;">）部分引用了外部</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">x (</span><span style="font-size: 10pt; font-family: 宋体;">函数参数在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">里是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量，译注：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">x</span><span style="font-size: 10pt; font-family: 宋体;">就是所谓的自由变量，这里形成了闭包</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">)</span><span style="font-size: 10pt; font-family: 宋体;">。尽管如此，当</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add2</span><span style="font-size: 10pt; font-family: 宋体;">被调用时，生成</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add2</span><span style="font-size: 10pt; font-family: 宋体;">的函数</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add</span><span style="font-size: 10pt; font-family: 宋体;">已经返回。如果在栈中生成变量</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">x</span><span style="font-size: 10pt; font-family: 宋体;">，（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">x</span><span style="font-size: 10pt; font-family: 宋体;">在栈的）其栈槽将不复存在。（译注，此处的意思应该是说如果在栈保存变量</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">x</span><span style="font-size: 10pt; font-family: 宋体;">，那么在调用</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add2</span><span style="font-size: 10pt; font-family: 宋体;">的时候，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add</span><span style="font-size: 10pt; font-family: 宋体;">函数早已经返回，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">x</span><span style="font-size: 10pt; font-family: 宋体;">也在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add2</span><span style="font-size: 10pt; font-family: 宋体;">调用前就不在栈里头了，这就是那个著名难题）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
</div>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><!--[if gte vml 1]><v:shape id="_x0000_i1026" type="#_x0000_t75" style='width:415.5pt;height:141pt'>
<v:imagedata src="file:///C:\DOCUME~1\cy\LOCALS~1\Temp\msohtml1\08\clip_image002.gif" o:title="2" />
</v:shape><![endif]--><!--[if !vml]--><img src="http://www.blogjava.net/images/blogjava_net/killme2008/lua02.jpg" alt="" border="0" /><br />
<!--[endif]--><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 37.45pt;" align="left"><span style="font-size: 9pt; font-family: 宋体;">大多数过程语言通过限制词法范围（例如</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">python</span><span style="font-size: 9pt; font-family: 宋体;">），不提供</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">first-class</span><span style="font-size: 9pt; font-family: 宋体;">函数（例如</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Pascal</span><span style="font-size: 9pt; font-family: 宋体;">），或者都两者都采用（例如</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">c,</span><span style="font-size: 9pt; font-family: 宋体;">译注：也就是说</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">c</span><span style="font-size: 9pt; font-family: 宋体;">既不把函数当一等公民，也限制词法范围）来回避这个问题。函数式语言就没有那些限制。围绕着非纯粹函数语言比如</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Scheme</span><span style="font-size: 9pt; font-family: 宋体;">和</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">ML</span><span style="font-size: 9pt; font-family: 宋体;">的研究已经产生了大量的关于闭包的编译技术的知识（参见</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">[19, 1, 21]</span><span style="font-size: 10pt; font-family: 宋体;">）。尽管如此，这些工作并没有尽力去限制编译器的复杂性。以优化的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Scheme</span><span style="font-size: 10pt; font-family: 宋体;">编译器</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Bigloo</span><span style="font-size: 10pt; font-family: 宋体;">的控制流分</span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 37.45pt;" align="left"><img src="http://www.blogjava.net/images/blogjava_net/killme2008/lua03.jpg" alt="" border="0" /><br />
</p>
<p class="MsoNormal" style="text-align: left; text-indent: 37.45pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">析阶段为例，（它的实现）比</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">实现的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">10</span><span style="font-size: 10pt; font-family: 宋体;">倍还大：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Bigloo <st1:chmetcnv tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="2.6" unitname="F" w:st="on">2.6f</st1:chmetcnv></span><span style="font-size: 10pt; font-family: 宋体;">的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Cfa</span><span style="font-size: 10pt; font-family: 宋体;">模块源码有</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">106,350</span><span style="font-size: 10pt; font-family: 宋体;">行</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"> VS. 10,155</span><span style="font-size: 10pt; font-family: 宋体;">行的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua5.0</span><span style="font-size: 10pt; font-family: 宋体;">核心。正如第</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">2</span><span style="font-size: 10pt; font-family: 宋体;">部分已经解释过的（原因），</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">需要简单。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><!--[if gte vml 1]><v:shape id="_x0000_i1027" type="#_x0000_t75" style='width:415.5pt;height:285.75pt'>
<v:imagedata src="file:///C:\DOCUME~1\cy\LOCALS~1\Temp\msohtml1\08\clip_image003.png" o:title="3" />
</v:shape><![endif]--><!--[if !vml]--><!--[endif]--><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 41.6pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">使用了一个称为</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">的结构来实现闭包。任何外部</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量的访问都是通过一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">间接进行的。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Upvalue</span><span style="font-size: 10pt; font-family: 宋体;">初始指向的是变量存活位置的栈槽（参见图</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">4</span><span style="font-size: 10pt; font-family: 宋体;">的左半部分）。当变量（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">x</span><span style="font-size: 10pt; font-family: 宋体;">）已经离开作用域（译注，也就是这里的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add</span><span style="font-size: 10pt; font-family: 宋体;">函数返回时），它就迁移到</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">结构本身一个槽中（参见图</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">4</span><span style="font-size: 10pt; font-family: 宋体;">的右半部分）。因为（对变量的）访问是间接地通过</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">结构中的一个指针进行的，因此这个迁移对于任何写或者读该变量的代码都是透明的。不像它的内嵌函数（译注：例子的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add2</span><span style="font-size: 10pt; font-family: 宋体;">，它是指外部函数</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">add</span><span style="font-size: 10pt; font-family: 宋体;">），声明变量的函数访问该变量就像访问它的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量一样：直接到栈。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 41.6pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">通过每个变量最多创建一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">结构并且在必要的时候复用它们，可变状态得以在闭包之间正确地共享。为了保证这一约束，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">维持一个链表，里面是一个栈里（图</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">4</span><span style="font-size: 10pt; font-family: 宋体;">中的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">pending vars</span><span style="font-size: 10pt; font-family: 宋体;">列表）的所有</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">open upvalue</span><span style="font-size: 10pt; font-family: 宋体;">（所谓</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">open upvalue</span><span style="font-size: 10pt; font-family: 宋体;">，是指仍然指向栈的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">结构）。当</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">创建一个新的闭包的时候，它遍历所有的外部</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量。对于每个（外部</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">）变量，如果它在列表中找到一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">open upvalue</span><span style="font-size: 10pt; font-family: 宋体;">，那么它就复用这个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">结构。否则，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">就创建一个新的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">upvalue</span><span style="font-size: 10pt; font-family: 宋体;">并将它放入链表。注意到列表搜索只是探测了少数几个节点，因为列表最多包含一个被内嵌函数使用的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量的项。当一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">closed
upvalue</span><span style="font-size: 10pt; font-family: 宋体;">不再被任何闭包引用的时候，它最后将被当作垃圾并回收。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 41.6pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">一个函数允许访问一个不是它的直接外围函数的外部</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量，只要（这个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">变量）是外部函数的（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">outer function</span><span style="font-size: 10pt; font-family: 宋体;">）。在那种情况下，甚至在闭包被创建的时候，（外部</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">local</span><span style="font-size: 10pt; font-family: 宋体;">）变量可能就不在栈里了。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">使用扁平闭包（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">flat
</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">closures</span><span style="font-size: 10pt; font-family: 宋体;">）解决这种情况</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">[5]</span><span style="font-size: 10pt; font-family: 宋体;">。通过扁平闭包，一个函数无论何时去访问一个不属于它的外围函数的外部变量，这个变量都将进入外围函数的闭包。从而当一个函数被实例化的时候，所有进入它闭包的变量要么在外围函数的栈里面，要么在外围函数的闭包里。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p><img src ="http://www.blogjava.net/killme2008/aggbug/191324.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-04-07 17:55 <a href="http://www.blogjava.net/killme2008/archive/2008/04/07/191324.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>lua 5.0的实现（翻译)1,2,3</title><link>http://www.blogjava.net/killme2008/archive/2008/04/07/191314.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Mon, 07 Apr 2008 09:25:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/04/07/191314.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/191314.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/04/07/191314.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/191314.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/191314.html</trackback:ping><description><![CDATA[<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">三个多月前翻译的，今天又找出来看看,后面的待整理下继续发,有错误的地方请不吝赐教。<br />
</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">原文：http://www.tecgraf.puc-rio.br/~lhf/ftp/doc/jucs05.pdf<br />
</span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">翻译：dennis zhuang</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"> (<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#107;&#105;&#108;&#108;&#109;&#101;&#50;&#48;&#48;&#56;&#64;&#103;&#109;&#97;&#105;&#108;&#46;&#99;&#111;&#109;">killme2008@gmail.com</a>)<span>&nbsp; </span><a href="http://www.blogjava.net/killme2008">http://www.blogjava.net/killme2008</a><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">转载请注明出处，谢谢。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: 宋体;">摘要：我们讨论了</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua 5.0</span><span style="font-size: 10pt; font-family: 宋体;">实现的主要新特性：基于寄存器的虚拟机，优化表的新算法以便（将表）用作数组，闭包的实现，以及</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">coroutines</span><span style="font-size: 9pt; font-family: 宋体;">（译注：协程）</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 9pt; font-family: 宋体;">关键字</span><span style="font-size: 9pt; font-family: CMBX9;" lang="EN-US">: </span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">compilers, virtual machines, hash tables, closures, coroutines<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 17.85pt; text-indent: -17.85pt;"><!--[if !supportLists]--><strong><span style="font-size: 16pt; font-family: CMR9;" lang="EN-US"><span>1.<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp; </span></span></span></strong><!--[endif]--><strong><span style="font-size: 16pt; font-family: 宋体;">介绍</span></strong><strong><span style="font-size: 16pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></strong></p>
<p class="MsoNormal"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua</span><span style="font-size: 9pt; font-family: 宋体;">作为内部使用的开发工具诞生于学术实验室中，现在却已经被世界范围内许多工业级项目所采用，广泛应用于游戏领域。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua</span><span style="font-size: 9pt; font-family: 宋体;">为什么能获得这样广泛的应用呢？我们认为答案就来源于我们的设计和实现目标上：提供一种简单、高效、可移植和轻量级的嵌入式脚本语言。这是</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua</span><span style="font-size: 9pt; font-family: 宋体;">自</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">1993</span><span style="font-size: 9pt; font-family: 宋体;">年诞生以来我们一直追求的目标，并在（语言的）演化过程中遵守。</span><span style="font-size: 10pt; font-family: 宋体;">这些特性，以及</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">一开始就被设计成嵌入大型应用的事实，才使它在早期被工业界所接受。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: 宋体;">广泛的应用产生了对（新的）语言的特性的需求。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">的许多特性来自于工业需求和用户反馈的推动。重要的例如</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua 5.0</span><span style="font-size: 10pt; font-family: 宋体;">引入的</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">coroutines</span><span style="font-size: 9pt; font-family: 宋体;">和即将到来的</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua 5.1</span><span style="font-size: 9pt; font-family: 宋体;">改进的垃圾收集实现，这些特性对于游戏（编程）特别重要。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 9pt; font-family: 宋体;">在这篇论文中，我们讨论了</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua 5.0</span><span style="font-size: 9pt; font-family: 宋体;">相比于</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua 4.0</span><span style="font-size: 9pt; font-family: 宋体;">的主要新特性：</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 9pt; font-family: 宋体;">基于寄存器的的虚拟机：传统上，绝大多数虚拟机的实际执行都是基于栈，这个趋势开始于</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Pascal</span><span style="font-size: 10pt; font-family: 宋体;">的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Pmachine,</span><span style="font-size: 10pt; font-family: 宋体;">延续到今天的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">java</span><span style="font-size: 10pt; font-family: 宋体;">虚拟机和微软的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">.net</span><span style="font-size: 10pt; font-family: 宋体;">环境。目前，尽管对于基于寄存器的虚拟机的兴趣逐渐增多（比如</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Perl6</span><span style="font-size: 10pt; font-family: 宋体;">计划中的新的虚拟机（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Parrot</span><span style="font-size: 10pt; font-family: 宋体;">）将是基于寄存器的），但是就我们所知，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua 5.0</span><span style="font-size: 10pt; font-family: 宋体;">是第一个被广泛使用的基于寄存器的虚拟机。我们将在第</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">7</span><span style="font-size: 10pt; font-family: 宋体;">部分描述这个虚拟机。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: 宋体;">优化表的新算法以便作为数组：</span><span style="font-size: 10pt; font-family: CMR10;"> </span><span style="font-size: 10pt; font-family: 宋体;">不像其他脚本语言，</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">并没有提供数组类型。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">使用整数索引的普通表来实现数组作为替代。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua 5.0</span><span style="font-size: 10pt; font-family: 宋体;">使用了一个新的算法，可以检测表是否被作为数组使用，并且可以自动将关联着数字索引的值存储进一个真实的数组，而不是将它们放进</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Hash</span><span style="font-size: 10pt; font-family: 宋体;">表。在第</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">4</span><span style="font-size: 10pt; font-family: 宋体;">部分我们将讨论这个算法。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: 宋体;">闭包的实现：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua 5.0</span><span style="font-size: 10pt; font-family: 宋体;">在词法层次上支持</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">first-class
</span><span style="font-size: 10pt; font-family: 宋体;">函数（译注：将函数作为一等公民）。这个机制导致一个著名的语言难题：使用基于数组的栈来存储激活记录。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua </span><span style="font-size: 10pt; font-family: 宋体;">使用了一个新办法来实现函数闭包，保存局部变量在（基于数组）的栈</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">(stack)</span><span style="font-size: 10pt; font-family: 宋体;">上，当它们被内嵌函数引用而从作用域逸出的时候才将它们转移到堆</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">(heap)</span><span style="font-size: 10pt; font-family: 宋体;">上。闭包的实现将在第</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">5</span><span style="font-size: 10pt; font-family: 宋体;">部分讨论。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: 宋体;">添加</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">coroutines</span><span style="font-size: 9pt; font-family: 宋体;">：</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"> lua 5.0</span><span style="font-size: 9pt; font-family: 宋体;">语言引入了</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">coroutines</span><span style="font-size: 9pt; font-family: 宋体;">。尽管</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">coroutines</span><span style="font-size: 9pt; font-family: 宋体;">的实现较为传统，但为了完整性我们将在第</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">6</span><span style="font-size: 9pt; font-family: 宋体;">部分做个简短的概况介绍。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 9pt; font-family: 宋体;">其他部分是为了讨论的完整性或者提供背景资料。在第</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">2</span><span style="font-size: 9pt; font-family: 宋体;">部分我们介绍了</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">的设计目标以及这个目标如何驱动实现的概况。在第</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">3</span><span style="font-size: 9pt; font-family: 宋体;">部分我们介绍了</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">是如何表示值的。尽管就这个过程本身没有什么新意，但是为了（理解）其他部分我们需要这些资料。最后，在第</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">8</span><span style="font-size: 9pt; font-family: 宋体;">部分，我们介绍了一个小型的基准测试来得到一些结论。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-indent: 19.5pt;"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: -18pt;"><!--[if !supportLists]--><strong><span style="font-size: 16pt; font-family: CMR9;" lang="EN-US"><span>2.<span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp; </span></span></span></strong><!--[endif]--><strong><span style="font-size: 16pt; font-family: CMR9;" lang="EN-US">lua</span></strong><strong><span style="font-size: 16pt; font-family: 宋体;">设计和实现概况</span></strong><strong><span style="font-size: 16pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></strong></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 9pt; font-family: 宋体;">在介绍部分提到过的，</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">实现的主要目标是：</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 9pt; font-family: 宋体;">简单性：我们探索我们能提供的最简单的语言，以及实现（这样的）语言的最简单的</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">C</span><span style="font-size: 9pt; font-family: 宋体;">代码。这就意味着（需要）不会偏离传统很远的拥有很少语言结构的简单语法。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 9pt; font-family: 宋体;">效率：我们探索编译和执行</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">程序的最快方法，这就意味着（需要）一个高效的、聪明的一遍扫描编译器和一个高效的虚拟机。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 9pt; font-family: 宋体;">可移植性：我们希望</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">能跑在尽可能多的平台上。我们希望能在任何地方不用修改地编译</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">核心，在任何一个带有合适的</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">解释器的平台上不用修改地运行</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">lua</span><span style="font-size: 9pt; font-family: 宋体;">程序。这就意味着一个对可移植性特别关注的干净的</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">ANSI C</span><span style="font-size: 9pt; font-family: 宋体;">的实现，例如避开</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">C</span><span style="font-size: 9pt; font-family: 宋体;">和标准库库中的陷阱缺陷，并确保能以</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">c++</span><span style="font-size: 9pt; font-family: 宋体;">方式干净地编译。我们追求</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">w</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">arning-free</span><span style="font-size: 10pt; font-family: 宋体;">的编译（实现）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 10pt; font-family: 宋体;">嵌入性：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">是一门扩展语言，它被设计用来为大型程序提供脚本设施。这个以及其他目标就意味着一个简单并且强大的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">C API</span><span style="font-size: 10pt; font-family: 宋体;">实现，但这样将更多地依赖内建的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">C</span><span style="font-size: 10pt; font-family: 宋体;">类型。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 10pt; font-family: 宋体;">嵌入的低成本：我们希望能容易地将</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">添加进一个应用，而不会使应用变的臃肿。这就意味着（需要）紧凑的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">C</span><span style="font-size: 10pt; font-family: 宋体;">代码和一个小的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">核心，扩展将作为用户库来添加。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: 宋体;">这些目标是有所权衡的。例如，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">经常被用作数据描述语言，用于保存和加载文件，有时是非常大的数据库</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">(</span><span style="font-size: 10pt; font-family: 宋体;">几</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">M</span><span style="font-size: 10pt; font-family: 宋体;">字节的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">程序不常见</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">)</span><span style="font-size: 10pt; font-family: 宋体;">。这就意味着我们需要一个快速的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">编译器。另一方面，我们想让</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">程序运行快速，这就意味着（需要）一个可以为虚拟机产生优秀代码的聪明的编译器。因此，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">LUA</span><span style="font-size: 10pt; font-family: 宋体;">编译器的实现必须在这两种需求中寻找平衡。尽管如此，编译器还是不能太大，否则将使整个发行包变的臃肿。目前编译器大约占</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">核心大小的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">30%</span><span style="font-size: 10pt; font-family: 宋体;">。在内存受限的应用中，比如嵌入式系统，嵌入不带有编译器的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">是可能的，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">程序将被离线预编译，然后被一个小模块（这个小模块也是快速的，因为它加载的是二进制文件）在运行时加载。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">使用了一个手写的扫描器和一个手写的递归下降解释器。直到</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">3.0</span><span style="font-size: 10pt; font-family: 宋体;">版本，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">还在使用一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">YACC</span><span style="font-size: 10pt; font-family: 宋体;">产生的解释器，这在语言的语法不够稳定的时候很有价值的。然而，手写的解释器更小、更高效、更轻便以及完全可重入，也能提供更好的出错信息（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">error message</span><span style="font-size: 10pt; font-family: 宋体;">）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt; text-indent: 19.5pt;"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">编译器没有使用中间代码表示（译注：也就是不生成中间代码）。当解释一个程序的时候，它以&#8220;</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">on-the-fly&#8221;</span><span style="font-size: 10pt; font-family: 宋体;">的方式给虚拟机发出指令。不过，它会进行一些优化。例如，它会推迟像变量和常量这样的基本表达式的代码生成。当它解释这样的表达式的时候，没有产生任何代码，而是使用一种简单的结构来表示它们。所以，判断一个给定指令的操作数是常量还是变量以及将它们的值直接应用在指令都变的非常容易，避免了不必要的和昂贵的移动。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: 宋体;">为了轻便地在许许多多不同的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">C</span><span style="font-size: 10pt; font-family: 宋体;">编译器和平台之间移植，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">不能使用许多解释器通常使用的技巧，例如</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">direct threaded code [8, 16]</span><span style="font-size: 10pt; font-family: 宋体;">。作为替代，它（译注：指</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">解释器）使用了标准的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">while-switch</span><span style="font-size: 10pt; font-family: 宋体;">分发循环。此处的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">C</span><span style="font-size: 10pt; font-family: 宋体;">代码看起来过于复杂，但是复杂性也是为了确保可移植性。当</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">在许多不同的平台上（包括</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">64</span><span style="font-size: 10pt; font-family: 宋体;">位平台和一些</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">16</span><span style="font-size: 10pt; font-family: 宋体;">位平台）被很多不同的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">C</span><span style="font-size: 10pt; font-family: 宋体;">编译器编译，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">实现的可移植性一直以来变的越来越稳定了。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">我们认为我们已经达到我们的设计和实现目标了。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">是一门非常轻便的语言，它能跑在任何一个带有</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">ANSI C</span><span style="font-size: 10pt; font-family: 宋体;">编译器的平台上，从嵌入式系统到大型机。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">确实是轻量级的：例如，它在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">linux</span><span style="font-size: 10pt; font-family: 宋体;">平台上的独立解释器包括所有的标准库，占用的空间小于</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">150K;</span><span style="font-size: 10pt; font-family: 宋体;">核心更是小于</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">100K</span><span style="font-size: 10pt; font-family: 宋体;">。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">是高效的：独立的基准测试表明</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">是脚本语言（解释的、动态类型的语言）领域中最快的语言之一。主观上我们也认为</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">是一门简单的语言，语法上类似</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Pascal</span><span style="font-size: 10pt; font-family: 宋体;">，语义上类似</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Scheme</span><span style="font-size: 10pt; font-family: 宋体;">（译注：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lisp</span><span style="font-size: 10pt; font-family: 宋体;">的一种方言）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="margin-left: 18pt;"><strong><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">3</span></strong><strong><span style="font-size: 9pt; font-family: 宋体;">、值的表示</span></strong><strong><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US"><o:p></o:p></span></strong></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua</span><span style="font-size: 9pt; font-family: 宋体;">是动态类型语言：类型依附于值而不是变量。</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">Lua</span><span style="font-size: 9pt; font-family: 宋体;">有</span><span style="font-size: 9pt; font-family: CMR9;" lang="EN-US">8</span><span style="font-size: 9pt; font-family: 宋体;">种基本类型：</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">nil</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">, </span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">boolean</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">, </span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">number</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">, </span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">string</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">, </span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">, </span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">function</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">,</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">userdata</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">, </span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">thread</span><span style="font-size: 10pt; font-family: 宋体;">。</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">Nil</span><span style="font-size: 10pt; font-family: 宋体;">是一个标记类型，它只拥有一个值也叫</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">nil</span><span style="font-size: 10pt; font-family: 宋体;">。</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">Boolean</span><span style="font-size: 10pt; font-family: 宋体;">就是通常的</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">true</span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">false</span><span style="font-size: 10pt; font-family: 宋体;">。</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">Number</span><span style="font-size: 10pt; font-family: 宋体;">是双精度浮点数，对应于</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">C</span><span style="font-size: 10pt; font-family: 宋体;">语言中的</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">double</span><span style="font-size: 10pt; font-family: 宋体;">类型，但用</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">float</span><span style="font-size: 10pt; font-family: 宋体;">或者</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">long</span><span style="font-size: 10pt; font-family: 宋体;">作为替代来编译</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">也很容易（不少游戏</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">consoles</span><span style="font-size: 10pt; font-family: 宋体;">或者小机器都缺乏对</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">double</span><span style="font-size: 10pt; font-family: 宋体;">的硬件支持）</span><span style="font-size: 10pt; font-family: 宋体;">。</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">String</span><span style="font-size: 10pt; font-family: 宋体;">是有显式大小的字节数组，因此可以存储任意的二进制类型，包括嵌入零。</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">Table</span><span style="font-size: 10pt; font-family: 宋体;">类型就是关联的数组，可以用任何值做索引（除了</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">nil</span><span style="font-size: 10pt; font-family: 宋体;">），也可以持有任何值。</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">Function</span><span style="font-size: 10pt; font-family: 宋体;">是依据与</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">虚拟机连接的协议编写的</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">函数或者</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">C</span><span style="font-size: 10pt; font-family: 宋体;">函数。</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">Userdata</span><span style="font-size: 10pt; font-family: 宋体;">本质上是指向用户内存区块（</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">user memory block</span><span style="font-size: 10pt; font-family: 宋体;">）的指针，有两种风格：重量级</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">,</span><span style="font-size: 10pt; font-family: 宋体;">由</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">分配块并由</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">GC</span><span style="font-size: 10pt; font-family: 宋体;">回收；轻量级，由用户分配和释放（内存）块。最后，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">thread</span><span style="font-size: 10pt; font-family: 宋体;">表示</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">coroutines</span><span style="font-size: 10pt; font-family: 宋体;">。所有类型的值都是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">first-class</span><span style="font-size: 10pt; font-family: 宋体;">值：我们可以将它们作为全局变量、局部变量和</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">table</span><span style="font-size: 10pt; font-family: 宋体;">的域来存储，作为参数传递给函数，作为函数的返回值等等。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">typedef struct {<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;</span>typedef union {<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">int t; <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>GCObject
*gc;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">Value v; <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>void *p;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">} TObject; <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>lua_Number n;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 215pt;" align="left"><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">int b;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 185pt;" align="left"><span style="font-size: 10pt; font-family: CMTT10;" lang="EN-US">} Value;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 60pt;" align="left"><span style="font-size: 10pt; font-family: CMBX10;" lang="EN-US">Figure 1: </span><span style="font-size: 10pt; font-family: 宋体;">带标签的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">表示</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">值</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 60pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 60pt;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Lua</span><span style="font-size: 10pt; font-family: 宋体;">将值表示为带标签的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union(tagged unions)</span><span style="font-size: 10pt; font-family: 宋体;">，也就是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">pairs(t,v)</span><span style="font-size: 10pt; font-family: 宋体;">，其中</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">t</span><span style="font-size: 10pt; font-family: 宋体;">是一个决定了值</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">v</span><span style="font-size: 10pt; font-family: 宋体;">类型的整数型标签，而</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">v</span><span style="font-size: 10pt; font-family: 宋体;">是一个实现了</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">类型的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">C</span><span style="font-size: 10pt; font-family: 宋体;">语言的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">结构。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Nil</span><span style="font-size: 10pt; font-family: 宋体;">拥有一个单独的值（译注：也就是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">nil</span><span style="font-size: 10pt; font-family: 宋体;">）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Booleans</span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">numbers</span><span style="font-size: 10pt; font-family: 宋体;">被实现为&#8220;拆箱式&#8221;的值：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">v</span><span style="font-size: 10pt; font-family: 宋体;">在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">中直接表示这些类型的值。这就意味着</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">（译注：指图中的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Value</span><span style="font-size: 10pt; font-family: 宋体;">）必须有足够的空间容纳</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">double</span><span style="font-size: 10pt; font-family: 宋体;">（类型）。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Strings,tables,
functions, threads, </span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"> userdata</span><span style="font-size: 10pt; font-family: 宋体;">类型的值通过引用来实现：</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">v</span><span style="font-size: 10pt; font-family: 宋体;">拥有指向实现这些类型的结构的指针。这些结构（译注：指实现</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Strings,tables, functions, threads, </span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"> userdata</span><span style="font-size: 10pt; font-family: 宋体;">这些类型的具体结构）共享一个共同的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">head</span><span style="font-size: 10pt; font-family: 宋体;">，用来保存用于垃圾收集的信息。结构的剩下的部分专属于各自的类型。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><span>&nbsp;</span>Figure1</span><span style="font-size: 10pt; font-family: 宋体;">展示了一个实际的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">值的实现。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">TObject</span><span style="font-size: 10pt; font-family: 宋体;">是这个实现的主要结构体：它表示了上文描述的带标签的联合体（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">tagged unions</span><span style="font-size: 10pt; font-family: 宋体;">）</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"> (t,v)</span><span style="font-size: 10pt; font-family: 宋体;">。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Value</span><span style="font-size: 10pt; font-family: 宋体;">是实现了值的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">类型。类型</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">nil</span><span style="font-size: 10pt; font-family: 宋体;">的值没有显式表示在这个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">类型中是因为标签已经足够标识它们。域</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">n</span><span style="font-size: 10pt; font-family: 宋体;">用来表示</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">numbers</span><span style="font-size: 10pt; font-family: 宋体;">类型（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua_Number</span><span style="font-size: 10pt; font-family: 宋体;">默认是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">double</span><span style="font-size: 10pt; font-family: 宋体;">类型）。同样，域</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">b</span><span style="font-size: 10pt; font-family: 宋体;">是给</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">booleans</span><span style="font-size: 10pt; font-family: 宋体;">类型用的，域</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">p</span><span style="font-size: 10pt; font-family: 宋体;">是给轻量级的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">userdata</span><span style="font-size: 10pt; font-family: 宋体;">类型。而域</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">gc</span><span style="font-size: 10pt; font-family: 宋体;">是为会被垃圾回收的其他类型准备的（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">(strings, tables, functions, </span><span style="font-size: 10pt; font-family: 宋体;">重量级</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">userdata, </span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">threads)</span><span style="font-size: 10pt; font-family: 宋体;">。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">使用带标签的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">实现</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">值的一个后果就是拷贝值的代价稍微昂贵了一点：在一台支持</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">64</span><span style="font-size: 10pt; font-family: 宋体;">位</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">double</span><span style="font-size: 10pt; font-family: 宋体;">类型的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">32</span><span style="font-size: 10pt; font-family: 宋体;">位机器上，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">TObject</span><span style="font-size: 10pt; font-family: 宋体;">的大小是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">12</span><span style="font-size: 10pt; font-family: 宋体;">字节（或者</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">16</span><span style="font-size: 10pt; font-family: 宋体;">字节，如果</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">double</span><span style="font-size: 10pt; font-family: 宋体;">按</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">8</span><span style="font-size: 10pt; font-family: 宋体;">字节对齐的话），因此拷贝一个值将需要拷贝</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">3</span><span style="font-size: 10pt; font-family: 宋体;">（或者</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">4</span><span style="font-size: 10pt; font-family: 宋体;">）个机器字长。尽管如此，想在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">ANSI C</span><span style="font-size: 10pt; font-family: 宋体;">中实现一个更好的值的表示是困难的。一些动态类型语言（例如</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Smalltalk80</span><span style="font-size: 10pt; font-family: 宋体;">的原始实现）在每个指针中使用多余的位来存储值的类型标签。这个技巧在绝大多数机器上正常工作，这是因为一个指针的最后两个或者三个位由于对齐将总是</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">0</span><span style="font-size: 10pt; font-family: 宋体;">，所以可以被用作他途。但是，这项技术既不是可移植的也无法在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">ANSI C</span><span style="font-size: 10pt; font-family: 宋体;">中实现，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">C </span><span style="font-size: 10pt; font-family: 宋体;">语言标准甚至都不保证指针适合任何整数类型，所以没有在指针上操作位的标准方法。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">减小值大小的另一个观点就是持有显式标签，从而避免在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">中放置一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">double</span><span style="font-size: 10pt; font-family: 宋体;">类型。例如，所有的</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">number</span><span style="font-size: 10pt; font-family: 宋体;">类型可以表示为堆分配的对象，就像</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">String</span><span style="font-size: 10pt; font-family: 宋体;">那样。（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">python</span><span style="font-size: 10pt; font-family: 宋体;">使用了这项技术，除了预先分配了一些小的整数值）。尽管如此，这样的表示方法将使语言变的非常缓慢。作为选择，整数的值可以表示位&#8220;拆箱式&#8221;的值，直接存储在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">union</span><span style="font-size: 10pt; font-family: 宋体;">中，而浮点值放在堆中。这个办法将极大地增加所有算术运算操作的实现复杂度。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left; text-indent: 19.5pt;" align="left"><span style="font-size: 10pt; font-family: 宋体;">类似早期的解释型语言，例如</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">Snobol [11] </span><span style="font-size: 10pt; font-family: 宋体;">和</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"> Icon [10]</span><span style="font-size: 10pt; font-family: 宋体;">，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">在一个</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">表中&#8220;拘留&#8221;</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">(</span><span style="font-size: 10pt; font-family: CMTI10;" lang="EN-US">internalizes)</span><span style="font-size: 10pt; font-family: 宋体;">字符串：（</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">表）没有重复地持有每个字符串的单独拷贝。此外，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">String</span><span style="font-size: 10pt; font-family: 宋体;">是不可变的：一个字符串一旦被&#8220;拘留&#8221;，将不能再被改变。字符串的哈希值依据一个混合了位和算术运算的简单表达式来计算，囊括所有的位。当字符串被&#8220;拘留&#8221;时，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">值保存（到</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">表），以支持更快的字符串比较和表索引。如果字符串太长的话，</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">hash</span><span style="font-size: 10pt; font-family: 宋体;">函数并不会用到字符串的所有字节，这有利于快速地散列长字符串。避免处理长字符串带来的性能损失是重要的，因为（这样的操作）在</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">中是很普遍的。例如，用</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US">lua</span><span style="font-size: 10pt; font-family: 宋体;">处理文件的时候经常将整个文件内容作为一个单独的长字符串读入内存。</span><span style="font-size: 10pt; font-family: CMR10;" lang="EN-US"><o:p></o:p></span></p><img src ="http://www.blogjava.net/killme2008/aggbug/191314.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-04-07 17:25 <a href="http://www.blogjava.net/killme2008/archive/2008/04/07/191314.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ruby性能优化的几个Tip(update)</title><link>http://www.blogjava.net/killme2008/archive/2008/03/27/188936.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Thu, 27 Mar 2008 01:46:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/03/27/188936.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/188936.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/03/27/188936.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/188936.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/188936.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 数据都是在我的机器上测试所得，我的机器配置:AMD athlon 64 x2 Dual 4000+ 2.11Ghz,1.87G内存。cruby版本是1.8.6,jruby是1.1RC3。操作系统是xp sp2。<br />
<br />
1、将繁忙的循环放在内层，比如下面的代码：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">a</span><span style="color: #000000;">=</span><span style="color: #000000;">0&nbsp;<br />
</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;i&nbsp;</span><span style="color: #0000ff;">in</span><span style="color: #000000;">&nbsp;0..</span><span style="color: #000000;">1000</span><span style="color: #000000;"><br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;j&nbsp;</span><span style="color: #0000ff;">in</span><span style="color: #000000;">&nbsp;0..</span><span style="color: #000000;">10</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a</span><span style="color: #000000;">+=</span><span style="color: #000000;">(i</span><span style="color: #000000;">+</span><span style="color: #000000;">j)<br />
&nbsp;&nbsp;end<br />
end<br />
</span></div>
替换成：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;j&nbsp;</span><span style="color: #0000ff;">in</span><span style="color: #000000;">&nbsp;0..</span><span style="color: #000000;">10</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;i&nbsp;</span><span style="color: #0000ff;">in</span><span style="color: #000000;">&nbsp;0..</span><span style="color: #000000;">1000</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;a</span><span style="color: #000000;">+=</span><span style="color: #000000;">(i</span><span style="color: #000000;">+</span><span style="color: #000000;">j)<br />
&nbsp;&nbsp;&nbsp;end<br />
end</span></div>
cruby提升15%左右，而jruby提升30%以上。<br />
<br />
2、乘法运算换成幂运算，cruby降低了200%以上，jruby仅降低30%。也就是说幂运算尽量换算成乘法运算。结论：幂运算换成乘法运算，乘法运算换成加法运算，多数情况下都能对性能有所提高，但请以实际测量为准。<br />
<br />
3、100*2 替换成 100&lt;&lt;1，jruby提升8左右%,c ruby提升在0到3%左右。结论：乘以2或者除以2操作可以替换成位移操作，这个调整对性能提高有限，可能以降低代码可读性为代价。<br />
<br />
4、字符串累积 a+="abc" 替换成 a&lt;&lt;"abc" c ruby提升接近100%,jruby提升97%<br />
<br />
5、将case...when...end语句替换成if...elsif...end语句，cruby没有明显变化（甚至有所降低），而jruby却提高15%左右。同时，jruby的case...when...end语句的效率比cruby快上60%，if...elsif...end语句比cruby快上50%。结论：使用cruby，用case...when语句为好，而jruby则尽量使用if...elsif<br />
<br />
6、将case语句中的频率比较高的分支提前，cruby提升15%左右，jruby也是如此。将if...elsif...end语句中的频率比较高的部分提前，jruby提升比较少，大概在5%左右，而cruby可以达到10%。。结论：尽管频率高的语句提前，可以适当提升性能，但可以看到也是有限的，分支语句的顺序不能仅仅考虑频率，更应该兼顾逻辑，维持在同一个抽象层次上。<br />
<br />
7、任何一次代码调整，请都要测量一下，这些Tip仅仅是我在我的机器环境下的测试结果。这些调整策略对其他语言也大多有效，我是在读了《代码大全2》代码调整一章后做的测试，并应用到我的代码中了。<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/188936.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-03-27 09:46 <a href="http://www.blogjava.net/killme2008/archive/2008/03/27/188936.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用jprofiler监控jruby脚本</title><link>http://www.blogjava.net/killme2008/archive/2008/03/24/188253.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Mon, 24 Mar 2008 07:26:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/03/24/188253.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/188253.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/03/24/188253.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/188253.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/188253.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; jruby本质上也是启动一个jvm，然后去读Ruby脚本并解释执行（也可以编译），因此jprofiler理所当然也可以去监控jruby脚本的执行。<br />
执行&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">jruby&nbsp;hello.rb</span></div>
等价于执行：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">java&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">Xmx378m&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">Xss1024k&nbsp;&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">Djruby.home</span><span style="color: #000000;">=/</span><span style="color: #000000;">usr</span><span style="color: #000000;">/</span><span style="color: #000000;">local</span><span style="color: #000000;">/</span><span style="color: #000000;">jruby </span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -</span><span style="color: #000000;">Djruby.lib</span><span style="color: #000000;">=/</span><span style="color: #000000;">usr</span><span style="color: #000000;">/</span><span style="color: #000000;">local</span><span style="color: #000000;">/</span><span style="color: #000000;">jruby</span><span style="color: #000000;">/</span><span style="color: #000000;">lib&nbsp;Djruby.script</span><span style="color: #000000;">=</span><span style="color: #000000;">jruby&nbsp;org.jruby.Main&nbsp;hello.rb</span></div>
这一点，你可以通过ps aux |grep jruby 看到。因此配置jprofiler就简单了，在VM arguments加上这些参数（可以包括jruby的参数），比如我的VM arguments配置如下：<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">-</span><span style="color: #000000;">server&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">Xmx378m&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">Xss1024k&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">Djruby.script</span><span style="color: #000000;">=</span><span style="color: #000000;">jruby&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">Djruby.thread.pooling</span><span style="color: #000000;">=</span><span style="color: #000000;">true <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000000;">-</span><span style="color: #000000;">Djruby.jit.threshold</span><span style="color: #000000;">=</span><span style="color: #000000;">0&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">Djruby.compile.fastest</span><span style="color: #000000;">=</span><span style="color: #000000;">true </span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -</span><span style="color: #000000;">Djruby.home</span><span style="color: #000000;">=</span><span style="color: #000000;">D:\jruby\jruby</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">.1RC2&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">Djruby.lib</span><span style="color: #000000;">=</span><span style="color: #000000;">D:\jruby\jruby</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;">.1RC2\lib</span></div>
<br />
Main class or executable JAR填上：org.jruby.Main。然后就是Arguments一栏填上你的脚本位置：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">D:\ruby\lib\hello.rb</span></div>
<br />
最后，别忘了将jruby/lib目录下的bsf.jar和jruby.jar加入Class Path。<br />
<br />
大功告成，你可以用jprofiler去观察GC、线程和锁、Heap等等了。<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/188253.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-03-24 15:26 <a href="http://www.blogjava.net/killme2008/archive/2008/03/24/188253.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>发布swf-util 0.01</title><link>http://www.blogjava.net/killme2008/archive/2008/03/11/185376.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Tue, 11 Mar 2008 06:41:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/03/11/185376.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/185376.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/03/11/185376.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/185376.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/185376.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; swf-util是一个使用Ruby读取swf头信息（高度、宽度、文件大小、帧数等等）、压缩和解压缩swf文件的工具类库，改写自<a href="http://www.brooksandrus.com/blog/2006/08/11/lightweight-swf-header-reader-java-ii/">java版本</a>。<br />
项目主页：<a href="http://code.google.com/p/swf-util/">http://code.google.com/p/swf-util/</a><br />
协议：MIT License<br />
平台：JRuby or c <a title="" href="http://www.ruby-lang.org" >ruby</a> 1.8.x on linux<br />
依赖BitStruct，请到<a href="http://raa.ruby-lang.org/project/bit-struct/">这里</a>下载安装bit-struct。在windows上的Ruby Zlib的实现有问题，linux下正常，使用JRuby也可以。<br />
使用例子：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008000;">#</span><span style="color: #008000;">read&nbsp;swf&nbsp;head</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">require&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">swf_util</span><span style="color: #800000;">'<br />
<br />
</span><span style="color: #000000;">header</span><span style="color: #000000;">=</span><span style="color: #000000;">SwfUtil::read_header(</span><span style="color: #800000;">"</span><span style="color: #800000;">test.swf</span><span style="color: #800000;">"</span><span style="color: #000000;">)<br />
puts&nbsp;header.inspect<br />
header.version<br />
header.frame_rate<br />
header.width<br />
header.frame_count<br />
<img src="http://www.blogjava.net/Images/dot.gif" alt="" /><img src="http://www.blogjava.net/Images/dot.gif" alt="" /><br />
<br />
</span><span style="color: #008000;">#</span><span style="color: #008000;">decompress&nbsp;swf</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">SwfUtil::decompress_swf(</span><span style="color: #800000;">"</span><span style="color: #800000;">test.swf</span><span style="color: #800000;">"</span><span style="color: #000000;">)<br />
<br />
</span><span style="color: #008000;">#</span><span style="color: #008000;">compress&nbsp;swf</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">SwfUtil::compress_swf(</span><span style="color: #800000;">"</span><span style="color: #800000;">test.swf</span><span style="color: #800000;">"</span><span style="color: #000000;">)</span></div>
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/185376.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-03-11 14:41 <a href="http://www.blogjava.net/killme2008/archive/2008/03/11/185376.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用Ruby写了个NFA</title><link>http://www.blogjava.net/killme2008/archive/2008/02/25/182053.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Mon, 25 Feb 2008 09:46:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/02/25/182053.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/182053.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/02/25/182053.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/182053.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/182053.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 今天有点空闲，想想用Ruby写个NFA试试。从正则表达式构造NFA采用经典的Thompson算法:正则表达式 -&gt; 后缀表达式 -&gt; 构造NFA。构造了NFA后，用之匹配字符串。一句话，写了个玩具的正则表达式引擎，支持concatenation、alternation以及*、?、+量词，不支持反向引用和转义符。测试了下与Ruby自带的正则表达式引擎的性能对比，慢了3倍<img src="/CuteSoft_Client/CuteEditor/images/emcry.gif" alt="" align="absmiddle" border="0" />。构造NFA没什么问题，主要是匹配运行写的烂，有空再改改。<br />
<br />
nfa.rb<br />
<br />
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 0, 255);">module</span><span style="color: rgb(0, 0, 0);"> NFA<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;NFA<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">def</span><span style="color: rgb(0, 0, 0);">&nbsp;initialize(state)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@state</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">state<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">def</span><span style="color: rgb(0, 0, 0);">&nbsp;step(clist,c)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;clist&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;clist.size</span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);">0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nlist</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">[]&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;allNull&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;true<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;matched&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;false<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clist.each&nbsp;do&nbsp;</span><span style="color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);">t</span><span style="color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;!t.nil?<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;allNull&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;false&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;t.c</span><span style="color: rgb(0, 0, 0);">!=-</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;t.c&nbsp;</span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);">&nbsp;c&nbsp;</span><span style="color: rgb(0, 0, 0);">&amp;&amp;</span><span style="color: rgb(0, 0, 0);">&nbsp;t.end.type&nbsp;</span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">&nbsp;then<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;matched&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;true<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nlist.push(t.end.out1)&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;!t.end.out1.end.nil?&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nlist.push(t.end.out2)&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;!t.end.out2.end.nil?<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;elsif&nbsp;(t.c&nbsp;</span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);">&nbsp;c&nbsp;</span><span style="color: rgb(0, 0, 0);">&amp;&amp;</span><span style="color: rgb(0, 0, 0);">&nbsp;t.end.type&nbsp;</span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);">&nbsp;0)&nbsp;then<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;matched&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;ListUitls.new_list(t);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;elsif&nbsp;(t.c&nbsp;</span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">&amp;&amp;</span><span style="color: rgb(0, 0, 0);">&nbsp;!t.end.nil?)&nbsp;then<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nlist.push(t.end.out1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nlist.push(t.end.out2);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;step(nlist,&nbsp;c)&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;(allNull)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;step(nlist,&nbsp;c)&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;(!matched)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nlist<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">def</span><span style="color: rgb(0, 0, 0);">&nbsp;test?(s)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;match(@state,s)<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">def</span><span style="color: rgb(0, 0, 0);">&nbsp;match(state,s)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clist&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">[]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clist.push(state.out1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clist.push(state.out2);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s.each_byte&nbsp;do&nbsp;</span><span style="color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);">c</span><span style="color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; c&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">c</span><span style="color: rgb(0, 0, 0);">&amp;</span><span style="color: rgb(0, 0, 0);">0xFF</span><span style="color: rgb(0, 0, 0);">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clist&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;step(clist,&nbsp;c);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;false&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;clist.size</span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);">0<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;is_match?(clist)<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">def</span><span style="color: rgb(0, 0, 0);">&nbsp;is_match?(clist)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;clist.each&nbsp;&nbsp;do&nbsp;</span><span style="color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);">t</span><span style="color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;true&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;!t.nil?&nbsp;</span><span style="color: rgb(0, 0, 255);">and</span><span style="color: rgb(0, 0, 0);">&nbsp;t.c</span><span style="color: rgb(0, 0, 0);">==-</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">and</span><span style="color: rgb(0, 0, 0);">&nbsp;t.end&nbsp;</span><span style="color: rgb(0, 0, 255);">and</span><span style="color: rgb(0, 0, 0);">&nbsp;t.end.is_matched?&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;false<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;end<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;Paren<br />
&nbsp;&nbsp;&nbsp;&nbsp;attr_accessor:n_alt,:n_atom<br />
&nbsp;&nbsp;end<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;State<br />
&nbsp;&nbsp;&nbsp;&nbsp;attr_accessor&nbsp;:out1,:out2,:type<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">def</span><span style="color: rgb(0, 0, 0);">&nbsp;initialize(out1,out2)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@out1</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">out1<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@out2</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">out2<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@type</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">def</span><span style="color: rgb(0, 0, 0);">&nbsp;is_matched?<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;@type</span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);">0<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;end<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;Transition<br />
&nbsp;&nbsp;&nbsp;&nbsp;attr_accessor&nbsp;:c,:end<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">def</span><span style="color: rgb(0, 0, 0);">&nbsp;initialize(c)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@c</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">c<br />
&nbsp;&nbsp;&nbsp;&nbsp;end&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;end<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;Frame<br />
&nbsp;&nbsp;&nbsp;&nbsp;attr_accessor&nbsp;:start,:outs<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">def</span><span style="color: rgb(0, 0, 0);">&nbsp;initialize(start,outs)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@start</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">start<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@outs</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">outs<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;end<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">&nbsp;ListUitls<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">def</span><span style="color: rgb(0, 0, 0);">&nbsp;self.link(list,state)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.each{</span><span style="color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);">t</span><span style="color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);">&nbsp;t.end</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">state}<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">def</span><span style="color: rgb(0, 0, 0);">&nbsp;self.append(list1,list2)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list1</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);">list2<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">def</span><span style="color: rgb(0, 0, 0);">&nbsp;self.new_list(out)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">[]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result.push(out)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;end<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">def</span><span style="color: rgb(0, 0, 0);">&nbsp;self.compile(re)<br />
&nbsp;&nbsp;&nbsp;&nbsp;post&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;re2post(re)<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">raise</span><span style="color: rgb(0, 0, 0);">&nbsp;ArgumentError.new,</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">bad&nbsp;regexp!</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;post.nil?<br />
&nbsp;&nbsp;&nbsp;&nbsp;state&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;post2nfa(post);<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">raise</span><span style="color: rgb(0, 0, 0);">&nbsp;RuntimeError.new,</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">construct&nbsp;nfa&nbsp;from&nbsp;postfix&nbsp;fail!</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;state.nil?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;NFA.new(state);<br />
&nbsp;&nbsp;end<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">def</span><span style="color: rgb(0, 0, 0);">&nbsp;self.post2nfa(postfix)<br />
&nbsp;&nbsp;&nbsp;&nbsp;stack</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">[]<br />
&nbsp;&nbsp;&nbsp;&nbsp;s</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">nil<br />
&nbsp;&nbsp;&nbsp;&nbsp;t</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">t1</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">t2</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">nil&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;e1</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">e2</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">e</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">nil&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;nil&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;postfix.nil?<br />
&nbsp;&nbsp;&nbsp;&nbsp;postfix.each_byte&nbsp;do&nbsp;</span><span style="color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);">p</span><span style="color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;p.chr<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when&nbsp;</span><span style="color: rgb(128, 0, 0);">'</span><span style="color: rgb(128, 0, 0);">.</span><span style="color: rgb(128, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e2&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;stack.pop()&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e1&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;stack.pop()&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ListUitls.link(e1.outs,&nbsp;e2.start)&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stack.push(Frame.new(e1.start,&nbsp;e2.outs))&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when&nbsp;</span><span style="color: rgb(128, 0, 0);">'</span><span style="color: rgb(128, 0, 0);">|</span><span style="color: rgb(128, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e2&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;stack.pop()&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e1&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;stack.pop()&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t1&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;Transition.new(</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t2&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;Transition.new(</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">)&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t1.end&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;e1.start&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t2.end&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;e2.start&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;State.new(t1,&nbsp;t2)&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stack.push(Frame.new(s,&nbsp;ListUitls.append(e1.outs,&nbsp;e2.outs)))&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when&nbsp;</span><span style="color: rgb(128, 0, 0);">'</span><span style="color: rgb(128, 0, 0);">?</span><span style="color: rgb(128, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;stack.pop()&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t1&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;Transition.new(</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t2&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;Transition.new(</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">)&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t1.end&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;e.start&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;State.new(t1,&nbsp;t2)&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stack.push(Frame.new(s,&nbsp;ListUitls.append(e.outs,&nbsp;ListUitls.new_list(t2))))&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when&nbsp;</span><span style="color: rgb(128, 0, 0);">'</span><span style="color: rgb(128, 0, 0);">*</span><span style="color: rgb(128, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;stack.pop()&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t1&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;Transition.new(</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t2&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;Transition.new(</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t1.end&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;e.start&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;State.new(t1,&nbsp;t2)&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ListUitls.link(e.outs,&nbsp;s)&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stack.push(Frame.new(s,&nbsp;ListUitls.new_list(s.out2)))&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when&nbsp;</span><span style="color: rgb(128, 0, 0);">'</span><span style="color: rgb(128, 0, 0);">+</span><span style="color: rgb(128, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;stack.pop()&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t1&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;Transition.new(</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">)&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t2&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;Transition.new(</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t1.end&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;e.start&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;State.new(t1,&nbsp;t2)&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ListUitls.link(e.outs,&nbsp;s)&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stack.push(Frame.new(e.start,&nbsp;ListUitls.new_list(t2)))&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;Transition.new(p)&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;State.new(t,&nbsp;Transition.new(</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">))&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stack.push(Frame.new(s,&nbsp;ListUitls.new_list(s.out1)))&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;e&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;stack.pop()&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;nil&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;stack.size()</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">0<br />
&nbsp;&nbsp;&nbsp;&nbsp;end_state&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;State.new(nil,&nbsp;nil)&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;end_state.type</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">0<br />
&nbsp;&nbsp;&nbsp;&nbsp;e.outs.each&nbsp;do&nbsp;</span><span style="color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);">tran</span><span style="color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;tran.c</span><span style="color: rgb(0, 0, 0);">!=-</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t1&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;Transition.new(</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t2&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;Transition.new(</span><span style="color: rgb(0, 0, 0);">-</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">)&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">State.new(t1,t2)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tran.end</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">s<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s.out1.end</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">end_state<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s.out2.end</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">end_state<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tran.end</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">end_state&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;start&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;e.start&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;start&nbsp;<br />
&nbsp;&nbsp;end<br />
&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">def</span><span style="color: rgb(0, 0, 0);">&nbsp;self.re2post(re)<br />
&nbsp;&nbsp;&nbsp;&nbsp;n_alt&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;n_atom&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;0&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;result</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(128, 0, 0);">""</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;paren</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">[]<br />
&nbsp;&nbsp;&nbsp;&nbsp;re.each_byte&nbsp;do&nbsp;</span><span style="color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);">c</span><span style="color: rgb(0, 0, 0);">|</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;c.chr&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when&nbsp;</span><span style="color: rgb(128, 0, 0);">'</span><span style="color: rgb(128, 0, 0);">(</span><span style="color: rgb(128, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">&nbsp;then<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;(n_atom&nbsp;</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">)&nbsp;then<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n_atom</span><span style="color: rgb(0, 0, 0);">-=</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result</span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">.</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">Paren.new&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.n_alt&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;n_alt&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.n_atom&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;n_atom&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;paren.push(p)&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n_alt&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;n_atom&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;0<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when&nbsp;</span><span style="color: rgb(128, 0, 0);">'</span><span style="color: rgb(128, 0, 0);">|</span><span style="color: rgb(128, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">&nbsp;then<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;(n_atom&nbsp;</span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);">&nbsp;0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;nil<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">while</span><span style="color: rgb(0, 0, 0);">&nbsp;(n_atom</span><span style="color: rgb(0, 0, 0);">-=</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">)&nbsp;</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;0&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result</span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">.</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n_alt</span><span style="color: rgb(0, 0, 0);">+=</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when&nbsp;</span><span style="color: rgb(128, 0, 0);">'</span><span style="color: rgb(128, 0, 0);">)</span><span style="color: rgb(128, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">&nbsp;then<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;(paren.size()&nbsp;</span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);">&nbsp;0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;nil<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;(n_atom&nbsp;</span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);">&nbsp;0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;nil&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">while</span><span style="color: rgb(0, 0, 0);">&nbsp;(n_atom</span><span style="color: rgb(0, 0, 0);">-=</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">0&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result</span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">.</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">while</span><span style="color: rgb(0, 0, 0);">(n_alt</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">0)&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result</span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">|</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n_alt</span><span style="color: rgb(0, 0, 0);">-=</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;paren.pop()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n_alt&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;p.n_alt&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n_atom&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;p.n_atom&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n_atom</span><span style="color: rgb(0, 0, 0);">+=</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when&nbsp;</span><span style="color: rgb(128, 0, 0);">'</span><span style="color: rgb(128, 0, 0);">*</span><span style="color: rgb(128, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(128, 0, 0);">'</span><span style="color: rgb(128, 0, 0);">+</span><span style="color: rgb(128, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(128, 0, 0);">'</span><span style="color: rgb(128, 0, 0);">?</span><span style="color: rgb(128, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;(n_atom&nbsp;</span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);">&nbsp;0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;nil&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result</span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);">c&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">else</span><span style="color: rgb(0, 0, 0);">&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;(n_atom&nbsp;</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">)&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n_atom</span><span style="color: rgb(0, 0, 0);">-=</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result</span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">.</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result</span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(0, 0, 0);">c&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n_atom</span><span style="color: rgb(0, 0, 0);">+=</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);">&nbsp;nil&nbsp;</span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">&nbsp;paren.size()</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">0<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">while</span><span style="color: rgb(0, 0, 0);">&nbsp;(&nbsp;(n_atom</span><span style="color: rgb(0, 0, 0);">-=</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);">)</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">&nbsp;0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result</span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">.</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 255);">while</span><span style="color: rgb(0, 0, 0);">(n_alt</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);">0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;n_alt</span><span style="color: rgb(0, 0, 0);">-=</span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result</span><span style="color: rgb(0, 0, 0);">&lt;&lt;</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">|</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;result<br />
&nbsp;&nbsp;end<br />
end<br />
</span></div>
<br />
使用：<br />
<div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: rgb(0, 0, 0);">&nbsp;nfa&nbsp;</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">&nbsp;NFA::compile(</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">a(bb)+a(cdf)*</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br />
&nbsp;</span><span style="color: rgb(0, 0, 255);">assert</span><span style="color: rgb(0, 0, 0);">&nbsp;nfa.test?(</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">abba</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br />
&nbsp;</span><span style="color: rgb(0, 0, 255);">assert</span><span style="color: rgb(0, 0, 0);">&nbsp;nfa.test?(</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">abbbba</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br />
&nbsp;</span><span style="color: rgb(0, 0, 255);">assert</span><span style="color: rgb(0, 0, 0);">&nbsp;!nfa.test?(</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">a</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)&nbsp;<br />
&nbsp;</span><span style="color: rgb(0, 0, 255);">assert</span><span style="color: rgb(0, 0, 0);">&nbsp;!nfa.test?(</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">aa</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)&nbsp;<br />
&nbsp;</span><span style="color: rgb(0, 0, 255);">assert</span><span style="color: rgb(0, 0, 0);">&nbsp;nfa.test?(</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">abbacdf</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br />
&nbsp;</span><span style="color: rgb(0, 0, 255);">assert</span><span style="color: rgb(0, 0, 0);">&nbsp;nfa.test?(</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">abbbbacdfcdf</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br />
&nbsp;</span><span style="color: rgb(0, 0, 255);">assert</span><span style="color: rgb(0, 0, 0);">&nbsp;!nfa.test?(</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">bbbbacdfcdf</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br />
&nbsp;</span><span style="color: rgb(0, 0, 255);">assert</span><span style="color: rgb(0, 0, 0);">&nbsp;!nfa.test?(</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">abbbacdfcdf</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br />
&nbsp;</span><span style="color: rgb(0, 0, 255);">assert</span><span style="color: rgb(0, 0, 0);">&nbsp;!nfa.test?(</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">abbbbacdfdf</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)<br />
&nbsp;</span><span style="color: rgb(0, 0, 255);">assert</span><span style="color: rgb(0, 0, 0);">&nbsp;!nfa.test?(</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(128, 0, 0);">abbbbacdfdfg</span><span style="color: rgb(128, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">)</span></div>
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/182053.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-02-25 17:46 <a href="http://www.blogjava.net/killme2008/archive/2008/02/25/182053.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ruby小技巧：处理方法调用中的nil</title><link>http://www.blogjava.net/killme2008/archive/2008/02/19/180647.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Tue, 19 Feb 2008 05:39:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/02/19/180647.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/180647.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/02/19/180647.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/180647.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/180647.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 读blog看到的一个小技巧，原文在<a href="http://www.pgrs.net/2008/2/17/handling-nil-in-method-calls">这里</a>。<br />
&nbsp;&nbsp;&nbsp; 我们常常处理这样的代码：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">name</span><span style="color: #000000;">=</span><span style="color: #000000;">person?person.name:nil</span></div>
<br />
&nbsp;&nbsp;&nbsp; 取某个对象的一个属性，先判断对象是否为nil，不是nil就返回对象属性，否则返回nil。这样的代码写多了比较恶心，是否有比较有趣的方式来减少代码？作者给出了一段代码：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">module&nbsp;ObjectExtension<br />
&nbsp;</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;nil_or<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;self&nbsp;unless&nbsp;self.nil?<br />
&nbsp;&nbsp;o&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Object.new<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">&nbsp;o<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;method_missing(sym,&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">args);&nbsp;nil;&nbsp;end<br />
&nbsp;&nbsp;end<br />
&nbsp;&nbsp;o<br />
&nbsp;&nbsp;end<br />
end<br />
</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Object<br />
&nbsp;&nbsp;include&nbsp;ObjectExtension<br />
end<br />
</span></div>
<br />
&nbsp;&nbsp; 上面的代码为Object加入了扩展，为每个对象实例增加了一个nil_or方法，分析下这个方法：如果对象不为nil，马上返回self(也就是对象本身），否则生成一个新的对象，这个对象通过method_missing机制将所有的方法调用都返回nil(原文是用Class.new，生成的类将不会被GC，这里采用回复给出的方案，生成对象，在对象的metaclass上做method_missing)。那么现在代码可以写成：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">&nbsp;&nbsp;&nbsp; <strong>name</strong></span><strong><span style="color: #000000;">=</span><span style="color: #000000;">person.nil_or.name</span></strong></div>
是不是相当的DSL呢？<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/180647.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-02-19 13:39 <a href="http://www.blogjava.net/killme2008/archive/2008/02/19/180647.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JRuby 1.1 RC2  Released</title><link>http://www.blogjava.net/killme2008/archive/2008/02/18/180388.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Mon, 18 Feb 2008 01:43:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/02/18/180388.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/180388.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/02/18/180388.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/180388.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/180388.html</trackback:ping><description><![CDATA[<p>修正了很多bug，我关注的
JRUBY-1686也得到了修正，距离1.1的发布不远了。</p>
<p>The JRuby community is pleased to announce the release of JRuby 1.1 RC 2</p>
<p>Homepage: <a href="http://www.jruby.org/" rel="nofollow">http://www.jruby.org/</a><br />
Download: <a href="http://dist.codehaus.org/jruby/" rel="nofollow">http://dist.codehaus.org/jruby/</a></p>
<p>JRuby 1.1RC2 is the second release candidate of JRuby 1.1.&nbsp; JRuby 1.1<br />
represents a concerted focus on speed and refinement.&nbsp; <a title="" href="http://www.ruby-lang.org" >ruby</a> code can<br />
completely compile in an Ahead Of Time (AOT) or Just In Time (JIT) mode;<br />
yielding a faster <a title="" href="http://www.ruby-lang.org" >ruby</a>!&nbsp; It also uses less memory than our previous releases.</p>
<p>We need people to download JRuby 1.1RC2 and give us feedback.&nbsp; Test your<br />
applications and help us make JRuby 1.1 a great release.</p>
<p>Highlights:<br />
- 260 issues resolved since JRuby 1.1RC1<br />
- Large IO refactoring<br />
<strong>
- Memory improvements for JIT'd methods:<br />
&nbsp; - Control total number of methods JIT'd<br />
&nbsp; - Support a JIT cache between runtimes to return permgen<br />
&nbsp; - Reduce codesize of generated methods (50-70% reduction)</strong></p><img src ="http://www.blogjava.net/killme2008/aggbug/180388.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-02-18 09:43 <a href="http://www.blogjava.net/killme2008/archive/2008/02/18/180388.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JRuby中使用接口和抽象类</title><link>http://www.blogjava.net/killme2008/archive/2008/02/15/180078.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Fri, 15 Feb 2008 06:34:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/02/15/180078.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/180078.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/02/15/180078.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/180078.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/180078.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 要在JRuby中实现java接口，接口<strong>include</strong>进来，实现接口方法即可，例如实现java.lang.Runnable接口做线程处理：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">require 'java'<br />
include_class 'java.lang.Runnable'<br />
class</span><span style="color: #000000;">&nbsp;TestRunnable<br />
&nbsp;&nbsp;&nbsp;&nbsp;include&nbsp;Runnable<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;initialize(name)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@name</span><span style="color: #000000;">=</span><span style="color: #000000;">name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;run<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">hello,</span><span style="color: #800000;">"</span><span style="color: #000000;">+</span><span style="color: #000000;">@name<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
end<br />
</span></div>
<br />
&nbsp;&nbsp;&nbsp; 要在JRuby中继承抽象类，实现其中的抽象方法，方法稍微麻烦点，需要cglib，到<a href="http://sourceforge.net/project/showfiles.php?group_id=56933">这里</a>下载cglib-nodep-2.1_3.jar，写个通用库abstract_class.rb方便处理:<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">load&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">cglib-nodep-2.1_3.jar</span><span style="color: #800000;">'</span><span style="color: #000000;"><br />
<br />
</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Object<br />
&nbsp;&nbsp;include&nbsp;Java<br />
&nbsp;&nbsp;include_class&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">net.sf.cglib.proxy.Enhancer</span><span style="color: #800000;">"</span><span style="color: #000000;"><br />
&nbsp;&nbsp;include_class&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">net.sf.cglib.proxy.NoOp</span><span style="color: #800000;">"</span><span style="color: #000000;"><br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">self<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;method_missing(mname,&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">args,&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">block)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unless&nbsp;mname&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;:abstract_impl&nbsp;</span><span style="color: #0000ff;">and</span><span style="color: #000000;">&nbsp;respond_to?(:java_class)&nbsp;</span><span style="color: #0000ff;">and</span><span style="color: #000000;">&nbsp;JavaLang::reflect::Modifier.isAbstract(JavaLang::Class.for_name(java_class.name).modifiers)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;generate_abstract_impl(args,&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">block)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;generate_abstract_impl(args,&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">block)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;factory&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Enhancer.new<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;factory.setSuperclass(java_class)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;factory.setInterfaces(java_class.interfaces.to_java(</span><span style="color: #800000;">"</span><span style="color: #800000;">java.lang.Class</span><span style="color: #800000;">"</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;factory.setCallback(NoOp::INSTANCE)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;object_args&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;args.map&nbsp;{&nbsp;</span><span style="color: #000000;">|</span><span style="color: #000000;">arg</span><span style="color: #000000;">|</span><span style="color: #000000;">&nbsp;Java.ruby_to_java(arg)&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class_arguments&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;object_args.map&nbsp;{</span><span style="color: #000000;">|</span><span style="color: #000000;">arg</span><span style="color: #000000;">|</span><span style="color: #000000;">&nbsp;arg.java_class}.to_java(</span><span style="color: #800000;">"</span><span style="color: #800000;">java.lang.Class</span><span style="color: #800000;">"</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;generated_class&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;factory.create(class_arguments,&nbsp;object_args.to_java(</span><span style="color: #800000;">"</span><span style="color: #800000;">java.lang.Object</span><span style="color: #800000;">"</span><span style="color: #000000;">))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ruby_class&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Class.new(generated_class.</span><span style="color: #0000ff;">class</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ruby_class.class_eval(</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">block)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;ruby_class.new(</span><span style="color: #000000;">*</span><span style="color: #000000;">args)<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;end<br />
&nbsp;&nbsp;<br />
end</span></div>
<br />
&nbsp;&nbsp;&nbsp; 使用的话，require一下abstract_class，例如我们要继承java.util.TimerTask，实现其中的run方法：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">$:.unshift&nbsp;File.join(File.dirname(</span><span style="color: #800080;">__FILE__</span><span style="color: #000000;">),</span><span style="color: #800000;">'</span><span style="color: #800000;">.</span><span style="color: #800000;">'</span><span style="color: #000000;">)<br />
require&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">java</span><span style="color: #800000;">'</span><span style="color: #000000;"><br />
require&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">abstract_class</span><span style="color: #800000;">'</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.TimerTask<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.util.Timer<br />
timer_task&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;TimerTask.abstract_impl&nbsp;do<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;run<br />
&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">timer&nbsp;task</span><span style="color: #800000;">"</span><span style="color: #000000;"><br />
&nbsp;&nbsp;end<br />
end<br />
<br />
Timer.new.schedule(timer_task,&nbsp;</span><span style="color: #000000;">1000</span><span style="color: #000000;">,&nbsp;</span><span style="color: #000000;">1000</span><span style="color: #000000;">)<br />
</span></div>
<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/180078.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-02-15 14:34 <a href="http://www.blogjava.net/killme2008/archive/2008/02/15/180078.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>google translator 0.2</title><link>http://www.blogjava.net/killme2008/archive/2008/02/14/179890.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Thu, 14 Feb 2008 03:15:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/02/14/179890.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/179890.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/02/14/179890.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/179890.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/179890.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 过去写的那个利用google在线翻译的<a href="http://www.blogjava.net/killme2008/archive/2007/02/06/98274.html">小脚本工具</a>一直在用，今天用的时候，突然想，我今年不是想加强下英语学习吗？那么把每天查过的单词保存下来，每天早上或者上班空闲期间花那么几分钟记忆复习下这些单词不是很好，毕竟技术性文章翻来覆去运用的单词就那么多，过去没有注意积累，导致常常还得重新查，所谓提高也就放在口头上了。说改就改，脚本语言改起来就是容易:<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008000;">#</span><span style="color: #008000;">利用google在线翻译，翻译中文&lt;-&gt;英文</span><span style="color: #008000;"><br />
#</span><span style="color: #008000;">author&nbsp;dennis</span><span style="color: #008000;"><br />
#</span><span style="color: #008000;">version&nbsp;0.2</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">require&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">net/http</span><span style="color: #800000;">'</span><span style="color: #000000;"><br />
$contents</span><span style="color: #000000;">=</span><span style="color: #000000;">Hash.new<br />
$dir</span><span style="color: #000000;">=</span><span style="color: #800000;">"</span><span style="color: #800000;">F:/English/</span><span style="color: #800000;">"</span><span style="color: #000000;"><br />
now</span><span style="color: #000000;">=</span><span style="color: #000000;">Time.now<br />
$today</span><span style="color: #000000;">=</span><span style="color: #800000;">"</span><span style="color: #800000;">#{now.year}#{now.month.to_s.rjust(2,'0')}#{now.day.to_s.rjust(2,'0')}</span><span style="color: #800000;">"</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;translate<br />
&nbsp;&nbsp;txt</span><span style="color: #000000;">=</span><span style="color: #000000;">STDIN.gets<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;txt.strip</span><span style="color: #000000;">==</span><span style="color: #800000;">'</span><span style="color: #800000;">e</span><span style="color: #800000;">'</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">or</span><span style="color: #000000;">&nbsp;txt.strip</span><span style="color: #000000;">==</span><span style="color: #800000;">'</span><span style="color: #800000;">exit</span><span style="color: #800000;">'</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">#</span><span style="color: #008000;">退出前保存</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;$contents.size</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">0&nbsp;then<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File.open(</span><span style="color: #800000;">"</span><span style="color: #800000;">#{$dir}#{$today}.txt</span><span style="color: #800000;">"</span><span style="color: #000000;">,</span><span style="color: #800000;">"</span><span style="color: #800000;">a+</span><span style="color: #800000;">"</span><span style="color: #000000;">)&nbsp;do&nbsp;</span><span style="color: #000000;">|</span><span style="color: #000000;">file</span><span style="color: #000000;">|</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$contents.each&nbsp;{</span><span style="color: #000000;">|</span><span style="color: #000000;">key,value</span><span style="color: #000000;">|</span><span style="color: #000000;">&nbsp;file.write(key.ljust(</span><span style="color: #000000;">20</span><span style="color: #000000;">)</span><span style="color: #000000;">+</span><span style="color: #000000;">value.ljust(</span><span style="color: #000000;">20</span><span style="color: #000000;">)</span><span style="color: #000000;">+</span><span style="color: #800000;">"</span><span style="color: #800000;">\n</span><span style="color: #800000;">"</span><span style="color: #000000;">)}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;exit<br />
&nbsp;&nbsp;end<br />
&nbsp;&nbsp;temp</span><span style="color: #000000;">=</span><span style="color: #000000;">txt.split(</span><span style="color: #800000;">'</span><span style="color: #800000;">&nbsp;</span><span style="color: #800000;">'</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;temp[</span><span style="color: #000000;">1</span><span style="color: #000000;">]</span><span style="color: #000000;">==</span><span style="color: #800000;">'</span><span style="color: #800000;">1</span><span style="color: #800000;">'</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">or</span><span style="color: #000000;">&nbsp;temp.size</span><span style="color: #000000;">==</span><span style="color: #000000;">1</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;langpair</span><span style="color: #000000;">=</span><span style="color: #800000;">'</span><span style="color: #800000;">en|zh-CN</span><span style="color: #800000;">'</span><span style="color: #000000;"><br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;langpair</span><span style="color: #000000;">=</span><span style="color: #800000;">'</span><span style="color: #800000;">zh-CN|en</span><span style="color: #800000;">'</span><span style="color: #000000;"><br />
&nbsp;&nbsp;end<br />
&nbsp;&nbsp;begin&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">#</span><span style="color: #008000;">使用代理&nbsp;&nbsp;</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">#</span><span style="color: #008000;">$proxy_addr&nbsp;=&nbsp;'192.168.9.25'</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;$proxy_port&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">8081</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;$proxy_user</span><span style="color: #000000;">=</span><span style="color: #800000;">'</span><span style="color: #800000;">test</span><span style="color: #800000;">'</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;$proxy_passwd</span><span style="color: #000000;">=</span><span style="color: #800000;">'</span><span style="color: #800000;">test</span><span style="color: #800000;">'</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;$proxy_addr<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Net::HTTP.Proxy($proxy_addr,$proxy_port,$proxy_user,$proxy_passwd).post_form(URI.parse(</span><span style="color: #800000;">"</span><span style="color: #800000;">http://translate.google.com/translate_t</span><span style="color: #800000;">"</span><span style="color: #000000;">),{</span><span style="color: #800000;">'</span><span style="color: #800000;">text</span><span style="color: #800000;">'</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">temp[0],</span><span style="color: #800000;">'</span><span style="color: #800000;">langpair</span><span style="color: #800000;">'</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">langpair})&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Net::HTTP.post_form(URI.parse(</span><span style="color: #800000;">"</span><span style="color: #800000;">http://translate.google.com/translate_t</span><span style="color: #800000;">"</span><span style="color: #000000;">),{</span><span style="color: #800000;">'</span><span style="color: #800000;">text</span><span style="color: #800000;">'</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">temp[0],</span><span style="color: #800000;">'</span><span style="color: #800000;">langpair</span><span style="color: #800000;">'</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">langpair})&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;response.body&nbsp;</span><span style="color: #000000;">=~</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">/&lt;</span><span style="color: #000000;">textarea.</span><span style="color: #000000;">*</span><span style="color: #000000;">?id</span><span style="color: #000000;">=</span><span style="color: #000000;">suggestion</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">(.</span><span style="color: #000000;">*</span><span style="color: #000000;">?)</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">\</span><span style="color: #000000;">/</span><span style="color: #000000;">textarea</span><span style="color: #000000;">&gt;/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;rescue&nbsp;&nbsp;StandardError&nbsp;</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">e<br />
&nbsp;&nbsp;&nbsp;&nbsp;$stderr.</span><span style="color: #0000ff;">print</span><span style="color: #000000;">&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">错误：</span><span style="color: #800000;">"</span><span style="color: #000000;">+</span><span style="color: #000000;">e<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;$</span><span style="color: #000000;">1</span><span style="color: #000000;">&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">翻译内容：</span><span style="color: #800000;">'</span><span style="color: #000000;">+</span><span style="color: #000000;">temp[0]<br />
&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">google返回:</span><span style="color: #800000;">'</span><span style="color: #000000;">+</span><span style="color: #000000;">result&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;result<br />
&nbsp;&nbsp;&nbsp;&nbsp;$contents[temp[0]]</span><span style="color: #000000;">=</span><span style="color: #000000;">result<br />
&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">-------------------退出请打e或者exit---------------</span><span style="color: #800000;">'</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;translate<br />
&nbsp;&nbsp;end<br />
end<br />
translate<br />
</span></div>
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/179890.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-02-14 11:15 <a href="http://www.blogjava.net/killme2008/archive/2008/02/14/179890.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JRuby的性能优化(update)</title><link>http://www.blogjava.net/killme2008/archive/2008/01/31/178725.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Thu, 31 Jan 2008 10:58:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/01/31/178725.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/178725.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/01/31/178725.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/178725.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/178725.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 越来越觉的JRuby是个很有前途的项目，结合Ruby的性感语法和java极其丰富的类库，况且有团队持续不断地修正bug、改进性能，这样的玩意完全有成为&#8220;少男杀手&#8221;的潜质。JRuby wiki上列出了性能优化的四条建议：<br />
1、调优编译器，JRuby早就弃暗投明跟随XRuby走上了编译这条牛B的道路，将Ruby Script编译成字节码，因此这个环节是断断不能忽略的。<br />
两种编译方式：<br />
AOT模式：直接生成class文件，脱了Ruby这层皮，咱就是人见人&#8220;爱&#8221;的java了。<br />
JIT模式：充分利用成熟的jit技术，咱不全脱，朦胧美才是真的美。默认从0.9.9版本开始就是开启的，关闭的话（要我说还不如全脱）<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">jruby&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">J</span><span style="color: #000000;">-</span><span style="color: #000000;">Djruby.jit.enabled</span><span style="color: #000000;">=</span><span style="color: #0000ff;">false</span></div>
<br />
<br />
2、关闭ObjectSpace<br />
ObjectSpace是Ruby用来操作所有运行时对象的模块，这个功能相当牛x。这个的实现在c ruby里是比较容易的，但是对于JRuby代价就比较昂贵了，其实就大部分情况下你基本用不到这个东东，那么最好就是关闭它，JRuby提供了<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">jruby&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">J</span><span style="color: #000000;">-</span><span style="color: #000000;">Djruby.objectspace.enabled</span><span style="color: #000000;">=</span><span style="color: #0000ff;">false</span></div>
选项来关闭它。<br />
<br />
3、开启线程池<br />
我们知道，在c ruby中的线程是绿色的轻量级线程，因此运行时就动不动开个百来十个&#8220;线程&#8221;跑一跑充下款爷；然而在JRuby中，线程的实现那可是实打实的本地线程（也就是Ruby线程与java线程一比一），你这么动不动上百个线程那不慢才怪了。因此JRuby提供了线程池选项，运行时尽可能地满足你的要求开线程，但是当短命的Ruby线程重复创建的时候，这些线程将被复用，这在大多数情况下能提高性能表现，特别是在每次调用都启动一个线程的情况下。不过具体效果还是要测试的实际数据说话。<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">jruby&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">J</span><span style="color: #000000;">-</span><span style="color: #000000;">Djruby.thread.pooling</span><span style="color: #000000;">=</span><span style="color: #0000ff;">true</span><span style="color: #000000;"> <br />
</span></div>
<br />
<br />
4、使用Java "server"模式虚拟机，地球淫都知道<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">jruby&nbsp;</span><span style="color: #000000;">-</span><span style="color: #000000;">J</span><span style="color: #000000;">-</span><span style="color: #000000;">server&nbsp;myscript.rb</span></div>
<br />
5、尽量使用最新的jdk，在我的测试中，jdk6跑jruby是效率最高的。<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/178725.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-01-31 18:58 <a href="http://www.blogjava.net/killme2008/archive/2008/01/31/178725.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>为BitStruct添加list类型</title><link>http://www.blogjava.net/killme2008/archive/2008/01/27/178025.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sun, 27 Jan 2008 07:53:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/01/27/178025.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/178025.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/01/27/178025.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/178025.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/178025.html</trackback:ping><description><![CDATA[<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;BitStruct<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;self.list(name,element)<br />
&nbsp;&nbsp;&nbsp;&nbsp;module_eval&nbsp;</span><span style="color: #000000;">&lt;&lt;-</span><span style="color: #000000;">HERE<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rest&nbsp;:body<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;</span><span style="color: #008000;">#</span><span style="color: #008000;">{name.to_s}=(elist)</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e</span><span style="color: #000000;">=</span><span style="color: #000000;">Object.const_get(:</span><span style="color: #008000;">#</span><span style="color: #008000;">{element})</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;elist.respond_to?&nbsp;:each&nbsp;</span><span style="color: #0000ff;">and</span><span style="color: #000000;">&nbsp;elist.respond_to?&nbsp;:[]&nbsp;</span><span style="color: #0000ff;">and</span><span style="color: #000000;">&nbsp;elist[0].is_a?&nbsp;e<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;elist.each{&nbsp;</span><span style="color: #000000;">|</span><span style="color: #000000;">value</span><span style="color: #000000;">|</span><span style="color: #000000;">&nbsp;self.body</span><span style="color: #000000;">+=</span><span style="color: #000000;">value}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;elsif&nbsp;elist.is_a?&nbsp;e<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.body</span><span style="color: #000000;">=</span><span style="color: #000000;">elist<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">raise</span><span style="color: #000000;">&nbsp;ArgumentError,elist.to_s</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #800000;">"</span><span style="color: #800000;">&nbsp;is&nbsp;not&nbsp;a&nbsp;#{element}</span><span style="color: #800000;">"</span><span style="color: #000000;">,caller<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;</span><span style="color: #008000;">#</span><span style="color: #008000;">{name.to_s}</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result</span><span style="color: #000000;">=</span><span style="color: #000000;">[]<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e</span><span style="color: #000000;">=</span><span style="color: #000000;">Object.const_get(:</span><span style="color: #008000;">#</span><span style="color: #008000;">{element})</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;size</span><span style="color: #000000;">=</span><span style="color: #000000;">e.new.size<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;num</span><span style="color: #000000;">=</span><span style="color: #000000;">self.body.size</span><span style="color: #000000;">/</span><span style="color: #000000;">size</span><span style="color: #000000;">-</span><span style="color: #000000;">1</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;i&nbsp;</span><span style="color: #0000ff;">in</span><span style="color: #000000;">&nbsp;0..num<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result[i]</span><span style="color: #000000;">=</span><span style="color: #000000;">e.new(self.body[i</span><span style="color: #000000;">*</span><span style="color: #000000;">size,size])<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;HERE<br />
&nbsp;&nbsp;end<br />
end</span></div>
利用Ruby的动态特性，很容易就达到了，使用的话：<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;A&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">BitStruct<br />
&nbsp;&nbsp;&nbsp;unsigned&nbsp;:id,</span><span style="color: #000000;">32</span><span style="color: #000000;"><br />
end<br />
</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;B</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">BitStruct<br />
&nbsp;&nbsp;&nbsp;list&nbsp;:aList,A<br />
end<br />
alist</span><span style="color: #000000;">=</span><span style="color: #000000;">[]<br />
</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;i&nbsp;</span><span style="color: #0000ff;">in</span><span style="color: #000000;">&nbsp;0..</span><span style="color: #000000;">10</span><span style="color: #000000;"><br />
&nbsp;&nbsp;a</span><span style="color: #000000;">=</span><span style="color: #000000;">A.new<br />
&nbsp;&nbsp;a.id</span><span style="color: #000000;">=</span><span style="color: #000000;">i<br />
&nbsp;&nbsp;alist.unshift&nbsp;a<br />
end<br />
b</span><span style="color: #000000;">=</span><span style="color: #000000;">B.new<br />
b.aList</span><span style="color: #000000;">=</span><span style="color: #000000;">alist<br />
b.aList.each{</span><span style="color: #000000;">|</span><span style="color: #000000;">e</span><span style="color: #000000;">|</span><span style="color: #000000;">&nbsp;puts&nbsp;e.id}</span></div>
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/178025.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-01-27 15:53 <a href="http://www.blogjava.net/killme2008/archive/2008/01/27/178025.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ruby处理二进制</title><link>http://www.blogjava.net/killme2008/archive/2008/01/25/177833.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Fri, 25 Jan 2008 10:56:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2008/01/25/177833.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/177833.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2008/01/25/177833.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/177833.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/177833.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 分析二进制协议或者存取二进制文件是个很常见的需求，Ruby的IO提供了对二进制的读操作，但是写入却只提供字符。并且读的操作也比较笨拙，例如，在c里面的话，我们一般是定义个struct，然后：<br />
<br />
fread(record, sizeof(record), 1, stream);<br />
<br />
在java里，也是比较容易，特别是nio引入了ByteBuffer之后就更方便了。Ruby的话，我得自己确定读多少个字节，并自己&#8220;组装&#8221;成原始数据，这显然太麻烦了，幸好，我们有<a href="http://redshift.sourceforge.net/bit-struct/">bit-struct</a> :)<br />
&nbsp;&nbsp;&nbsp; 到<a href="http://redshift.sourceforge.net/bit-struct/">主页</a>下载，解压之后参照README安装下就OK了。使用的话，也是先定义结构，然后new就行了：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">require&nbsp;</span><span style="color: #000000;">'</span><span style="color: #000000;">bit-struct</span><span style="color: #000000;">'</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Message&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;BitStruct<br />
&nbsp;&nbsp;&nbsp;&nbsp;signed&nbsp;:msg_length,</span><span style="color: #000000;">32</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;:type,</span><span style="color: #000000;">24</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;signed&nbsp;:uid,</span><span style="color: #000000;">32</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;:cmd,</span><span style="color: #000000;">16</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;rest&nbsp;&nbsp;:body<br />
end<br />
msg</span><span style="color: #000000;">=</span><span style="color: #000000;">Message.</span><span style="color: #0000ff;">new</span><span style="color: #000000;"><br />
file.read(msg)<br />
p&nbsp;msg.inspect</span></div>
<br />
bit-struct支持float,char,unsigned,signed,text,pad,nest,oct,hex，其中nest用于声明一个嵌套结构，例如：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Sub&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;BitStruct<br />
&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;:x,&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">8</span><span style="color: #000000;"><br />
&nbsp;end<br />
<br />
</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;A&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;BitStruct<br />
&nbsp;&nbsp;&nbsp;&nbsp;nest&nbsp;&nbsp;&nbsp;&nbsp;:n,&nbsp;&nbsp;Sub<br />
end<br />
<br />
a&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;A.new<br />
p&nbsp;a&nbsp;&nbsp;</span><span style="color: #008000;">#</span><span style="color: #008000;">&nbsp;==&gt;&nbsp;#&lt;A&nbsp;n=#&lt;Sub&nbsp;x=0&gt;&gt;</span></div>
<br />
如果你看下源码的话，会发现BitStruct继承String类，因此IO可以直接将BitStruct写入文件，内部自动帮你处理转换细节。<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/177833.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2008-01-25 18:56 <a href="http://www.blogjava.net/killme2008/archive/2008/01/25/177833.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一段小程序（Perl vs. Ruby)</title><link>http://www.blogjava.net/killme2008/archive/2007/12/07/166077.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Fri, 07 Dec 2007 08:30:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/12/07/166077.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/166077.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/12/07/166077.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/166077.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/166077.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 读《Perl语言入门》（第四版，我买的书，网上有个翻译质量很高的电子版）的第10章的习题，人见人爱的猜数游戏，用perl写出来大概这样：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #800080;">$num</span><span style="color: #000000;">=</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;(</span><span style="color: #800000;">1</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">rand</span><span style="color: #000000;">&nbsp;</span><span style="color: #800000;">100</span><span style="color: #000000;">);<br />
</span><span style="color: #0000ff;">print</span><span style="color: #000000;">&nbsp;</span><span style="font-weight: bold; color: #000000;">"</span><span style="font-weight: bold; color: #000000;">I&nbsp;have&nbsp;a&nbsp;number,guess&nbsp;it?:\n</span><span style="font-weight: bold; color: #000000;">"</span><span style="color: #000000;">;<br />
</span><span style="color: #0000ff;">while</span><span style="color: #000000;">(</span><span style="color: #000000;">&lt;&gt;</span><span style="color: #000000;">)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">chomp</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">next</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">unless</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">/\</span><span style="color: #000000;">d</span><span style="color: #000000;">+/</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800080;">$_</span><span style="color: #000000;">&gt;</span><span style="color: #800080;">$num</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">print</span><span style="color: #000000;">&nbsp;</span><span style="font-weight: bold; color: #000000;">"</span><span style="font-weight: bold; color: #000000;">Too&nbsp;high\n</span><span style="font-weight: bold; color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">:</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800080;">$_</span><span style="color: #000000;">==</span><span style="color: #800080;">$num</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">last</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">:</span><span style="color: #0000ff;">print</span><span style="color: #000000;">&nbsp;</span><span style="font-weight: bold; color: #000000;">"</span><span style="font-weight: bold; color: #000000;">Too&nbsp;low\n</span><span style="font-weight: bold; color: #000000;">"</span><span style="color: #000000;">;&nbsp;<br />
}</span></div>
&nbsp;&nbsp; 题外话：玩Perl的高人们别鄙视我，我是perl新手啊，如果写的不够&#8220;perl&#8221;，多多指点。<br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp; 这段代码转成ruby，可以这样写：<br />
<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">$num</span><span style="color: #000000;">=1+</span><span style="color: #000000;">(rand&nbsp;</span><span style="color: #000000;">100</span><span style="color: #000000;">)<br />
puts&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">I&nbsp;have&nbsp;a&nbsp;number&nbsp;guess&nbsp;it?</span><span style="color: #800000;">"</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">while</span><span style="color: #000000;">(true)<br />
&nbsp;&nbsp;&nbsp;gets.chomp<br />
&nbsp;&nbsp;&nbsp;next&nbsp;unless&nbsp;</span><span style="color: #000000;">~/</span><span style="color: #000000;">\d</span><span style="color: #000000;">+/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$_.to_i</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">$num?begin&nbsp;</span><span style="color: #0000ff;">print</span><span style="color: #000000;">&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">Too&nbsp;high\n</span><span style="color: #800000;">"</span><span style="color: #000000;">&nbsp;end:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$_.to_i</span><span style="color: #000000;">==</span><span style="color: #000000;">$num?&nbsp;begin&nbsp;</span><span style="color: #0000ff;">break</span><span style="color: #000000;">&nbsp;end:begin&nbsp;</span><span style="color: #0000ff;">print</span><span style="color: #000000;">&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">Too&nbsp;low\n</span><span style="color: #800000;">"</span><span style="color: #000000;">&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
end</span></div>
<br />
&nbsp;&nbsp;&nbsp; 看出来了吧，两者何其相似啊，包括perl里面人见人爱的$_，ruby也是支持的，唯一那么一点不同的地方就是last换成了break，然后是正则表达式左边多了个~，你完全可以将这个符号去掉，不过会有警告，最后就是Ruby中的要执行的表达式得放在begin...end里面，这一点让我琢磨了一段时间，还以为Ruby不支持呢。读《Perl语言入门》最大的乐趣除了妙趣横生的语言、古灵精怪的符号之外，就是寻找Ruby中的Perl痕迹，哦哦，那个味道相当重——骆驼的味道。不过现在Ruby不鼓励这样的写法，毕竟，程序是给人读的，因此可以改写一下：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">$num</span><span style="color: #000000;">=1+</span><span style="color: #000000;"><span style="color: #000000;">(rand&nbsp;</span><span style="color: #000000;">100)<br />
</span></span><span style="color: #000000;">puts&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">I&nbsp;have&nbsp;a&nbsp;number&nbsp;guess&nbsp;it?</span><span style="color: #800000;">"</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">while</span><span style="color: #000000;">(true)<br />
&nbsp;&nbsp;&nbsp;guess</span><span style="color: #000000;">=</span><span style="color: #000000;">STDIN.gets<br />
&nbsp;&nbsp;&nbsp;next&nbsp;unless&nbsp;guess</span><span style="color: #000000;">=~/</span><span style="color: #000000;">\d</span><span style="color: #000000;">+/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(guess.to_i</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">$num)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">Too&nbsp;high</span><span style="color: #800000;">"</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;elsif(guess.to_i</span><span style="color: #000000;">==</span><span style="color: #000000;">$num)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">break</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">Too&nbsp;low</span><span style="color: #800000;">"</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;end<br />
end</span></div>
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/166077.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-12-07 16:30 <a href="http://www.blogjava.net/killme2008/archive/2007/12/07/166077.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Lua学习小记——语言</title><link>http://www.blogjava.net/killme2008/archive/2007/11/29/164017.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Thu, 29 Nov 2007 08:05:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/11/29/164017.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/164017.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/11/29/164017.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/164017.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/164017.html</trackback:ping><description><![CDATA[1.起点，经典hello world:<br />
<div style="border: 1pt solid windowtext; padding: 1pt 4pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-left: 21pt; margin-right: 21pt;">
<p class="AltD" style="margin: 0cm 0cm 0.0001pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><span lang="EN-US">print(<span style="color: red;">"Hello World"</span>)</span></p>
</div>
这与大多数脚本语言没什么两样，总体来说如果你对JavaScript、Ruby、Python之类有所学习的话,LUA还是相当简单的<br />
<br />
2.函数定义，类似JS,用begin end代替大括号：<br />
<div style="border: 1pt solid windowtext; padding: 1pt 4pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-left: 21pt; margin-right: 21pt;">
<p class="AltD" style="margin: 0cm 0cm 0.0001pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><span style="color: blue;" lang="EN-US">function</span><span lang="EN-US"> fact (n)</span></p>
<p class="AltD" style="margin: 0cm 0cm 0.0001pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">if</span>
n == 0 <span style="color: blue;">then</span></span></p>
<p class="AltD" style="margin: 0cm 0cm 0.0001pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">return</span>
1</span></p>
<p class="AltD" style="margin: 0cm 0cm 0.0001pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">else<o:p></o:p></span></span></p>
<p class="AltD" style="margin: 0cm 0cm 0.0001pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">return</span>
n * fact(n-1)</span></p>
<p class="AltD" style="margin: 0cm 0cm 0.0001pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp; </span><span style="color: blue;">end<o:p></o:p></span></span></p>
<p class="AltD" style="margin: 0cm 0cm 0.0001pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><span style="color: blue;" lang="EN-US">end<o:p></o:p></span></p>
</div>
<br />
function其实就是lambda算子.<br />
<br />
3.&nbsp; 8种基本类型：<br />
<span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">nil</span><span style="font-size: 10.5pt; font-family: 宋体;">、</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">boolean</span><span style="font-size: 10.5pt; font-family: 宋体;">、</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">number</span><span style="font-size: 10.5pt; font-family: 宋体;">、</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">string</span><span style="font-size: 10.5pt; font-family: 宋体;">、</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">userdata</span><span style="font-size: 10.5pt; font-family: 宋体;">、</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">function</span><span style="font-size: 10.5pt; font-family: 宋体;">、</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">thread</span><span style="font-size: 10.5pt; font-family: 宋体;">和</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US">table<br />
<br />
boolean类型除了false和nil是false之外，其他都是true<br />
lua支持函数式编程，因此函数是一等公民，userdata用于存储C语言的数据，待深入。thread与多线程编程有关。table是lua的基本数据结构，是array和hash的综合体，比较奇怪的是默认索引从1开始，而不是通常的0。看例子：<br />
</span>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-left: 21pt; margin-right: 21pt;">
<p class="AltD" style="margin: 0cm 0cm 0.0001pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><span lang="EN-US">days = {<span style="color: red;">"Sunday"</span>, <span style="color: red;">"Monday"</span>, <span style="color: red;">"Tuesday"</span>,
<span style="color: red;">"Wednesday"</span>,</span></p>
<p class="AltD" style="margin: 0cm 0cm 0.0001pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><span lang="EN-US"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: red;">"Thursday"</span>, <span style="color: red;">"Friday"</span>,
<span style="color: red;">"Saturday"</span>}</span></p>
</div>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-left: 21pt; margin-right: 21pt;">
<p class="AltD" style="margin: 0cm 0cm 0.0001pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><span lang="EN-US">w = {x=0, y=0, label=<span style="color: red;">"console"</span>}</span></p>
</div>
<br />
4. lua与ruby一样支持多重赋值和函数可以返回多个值，常见控制结构没有什么好说的。<br />
<br />
5.可变参数，lua有很浓重的C味道，可变参数也与C一样，用...表示：<br />
<span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;; color: blue;" lang="EN-US">function</span><span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US"> g (a, b, ...) ... end<br />
<br />
也可以通过表来传递命名参数：<br />
</span>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-left: 21pt; margin-right: 21pt;">
<p class="AltD" style="margin: 0cm 0cm 0.0001pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><span lang="EN-US">rename{old=<span style="color: red;">"temp.lua"</span>, new=<span style="color: red;">"temp1.lua"</span>}</span></p>
</div>
<br />
6.局部变量的声明 local i=0，仅在声明的代码块内有效。如果没有声明为local，将自动成为全局变量，一个变量在赋值前是nil，通过将变量声明为nil可以删除该变量<br />
<span style="font-size: 10.5pt; font-family: &quot;Times New Roman&quot;;" lang="EN-US"><br />
7.LUA是有尾递归优化的，也提供了各种高阶函数以及闭包等等特性。<br />
<br />
8.loadstring函数，一般其他解释语言中的eval函数相似，不过他是返回一个chunk（每个chunk都是匿名函数）让你执行，比如<br />
</span>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-left: 21pt; margin-right: 21pt;">
<p class="AltD" style="margin: 0cm 0cm 0.0001pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><span lang="EN-US">f = loadstring(<span style="color: red;">"local a = 10; return a
+ 20"</span>)</span></p>
</div>
<div style="border: 1pt solid windowtext; padding: 1pt 4pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-left: 21pt; margin-right: 21pt;">
<p class="AltD" style="margin: 0cm 0cm 0.0001pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><span lang="EN-US">print(f())<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: green;">--&gt; 30<o:p></o:p></span></span></p>
</div>
也可以通过loadfile将整个文件载入作为chunk。<br />
<br />
9.require，用于加载文件，会搜索环境变量LUA_PATH设定的路径，同时能判断文件是否已经加载来避免重复加载。比较奇特的是路径的设置，与一般的路径完全不同，其实就是用?当占位符，然后require filename的时候，用filename代替这些文号，比如：<br />
<div style="border: 1pt dashed windowtext; padding: 1pt 4pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-left: 21pt; margin-right: 21pt;">
<p class="AltP" style="margin: 0cm 0cm 0.0001pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><span lang="EN-US">?;?.lua;c:\windows\?;/usr/local/lua/?/?.lua</span></p>
</div>
当你require 'lili'的时候，就会寻找下列路径的文件：<br />
<div style="border: 1pt dashed windowtext; padding: 1pt 4pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial; margin-left: 21pt; margin-right: 21pt;">
<p class="AltP" style="margin: 0cm 0cm 0.0001pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><span lang="EN-US">lili</span></p>
<p class="AltP" style="margin: 0cm 0cm 0.0001pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><span lang="EN-US">lili.lua</span></p>
<p class="AltP" style="margin: 0cm 0cm 0.0001pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><span lang="EN-US">c:\windows\lili</span></p>
<p class="AltP" style="margin: 0cm 0cm 0.0001pt; background: #e6e6e6 none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><span lang="EN-US">/usr/local/lua/lili/lili.lua</span></p>
</div>
<br />
10.lua通过loadlib函数可以加载动态链接库<br />
<br />
11.<span lang="EN-US">pcall</span><span style="font-family: 宋体;">在保护模式（</span><span lang="EN-US">protected mode</span><span style="font-family: 宋体;">）下执行函数内容，同时捕获所有的异常和错误。若一切正常，</span><span lang="EN-US">pcall</span><span style="font-family: 宋体;">返回</span><span lang="EN-US">true</span><span style="font-family: 宋体;">以及&#8220;被执行函数&#8221;的返回值；否则返回</span><span lang="EN-US">nil</span><span style="font-family: 宋体;">和错误信息。</span><br />
<br />
12.<br /><img src ="http://www.blogjava.net/killme2008/aggbug/164017.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-11-29 16:05 <a href="http://www.blogjava.net/killme2008/archive/2007/11/29/164017.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>得到singleton类？</title><link>http://www.blogjava.net/killme2008/archive/2007/10/31/157152.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Wed, 31 Oct 2007 03:33:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/10/31/157152.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/157152.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/10/31/157152.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/157152.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/157152.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 在Ruby中，无论类或者对象，都有一个singlton类（或者称为metaclass），有兴趣的话读读过去写的这篇《<a href="http://www.blogjava.net/killme2008/archive/2007/09/29/149452.html">Ruby的对象模型</a>》。当我们获取某个类或者对象的class属性时，其实会忽略c ruby层次上的singleton类，那么我们如何得到singleton类呢？比较有趣的做法：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">singletonclass</span><span style="color: #000000;">=</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">Test;self;end</span></div>
<br />
对于对象，也是如此：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">test</span><span style="color: #000000;">=</span><span style="color: #000000;">Test.</span><span style="color: #0000ff;">new</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">metaclass=class</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">test;self;end</span></div>
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/157152.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-10-31 11:33 <a href="http://www.blogjava.net/killme2008/archive/2007/10/31/157152.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ruby的对象模型</title><link>http://www.blogjava.net/killme2008/archive/2007/09/29/149452.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sat, 29 Sep 2007 01:43:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/09/29/149452.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/149452.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/09/29/149452.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/149452.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/149452.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; Ruby的对象模型，包含在下面这张图中：<br />
<img alt="" src="http://www.javaeye.com/topics/download/2fb4a83c-1a28-4aa0-aee0-4f77aafb8c2c" /><br />
<br />
&nbsp;&nbsp;&nbsp; 首先要知道，Ruby中的类也是对象，类相比于其他对象特殊的地方在于能够产生对象，既然类是对象，那么它显然也有类，也就是所谓类的类，这个类的类在Ruby中就是类的metaclass，图中的(OtherClass)，(OtherClass)就是类OtherClass的klass(C层次）,(OtherClass)存储了类的方法(类方法）和类的实例变量，并且是唯一的且不可实例化。在Ruby层次上我们想操作(otherclass)应该类似：<br />
&nbsp;&nbsp; <br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;OtherClass<br />
&nbsp;&nbsp;<br />
end<br />
</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">OtherClass<br />
&nbsp;&nbsp;attr_accessor:name&nbsp;</span><span style="color: #008000;">#</span><span style="color: #008000;">name是OtherClass的实例变量</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;test<br />
&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">hello</span><span style="color: #800000;">'</span><span style="color: #000000;"><br />
&nbsp;&nbsp;end<br />
end<br />
OtherClass.name</span><span style="color: #000000;">=</span><span style="color: #800000;">'</span><span style="color: #800000;">1</span><span style="color: #800000;">'</span><span style="color: #000000;"><br />
p&nbsp;OtherClass.name<br />
OtherClass.test</span></div>
&nbsp;&nbsp;&nbsp; 图中的instance是OtherClass的一个实例，那么显然instance的class是OtherClass，可是图中的(instance)又是什么呢？(instance)就是对象的singleton类，singleton类这个名称怪怪的，不过每个对象只能有一个singleton类的角度上说也可以理解。看看下面的例子：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;OtherClass<br />
end<br />
instance</span><span style="color: #000000;">=</span><span style="color: #000000;">OtherClass.new<br />
</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">instance<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;test<br />
&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">a.test</span><span style="color: #800000;">"</span><span style="color: #000000;"><br />
&nbsp;&nbsp;end<br />
&nbsp;&nbsp;attr_accessor:name<br />
end<br />
instance.test<br />
instance.name</span><span style="color: #000000;">=</span><span style="color: #800000;">"</span><span style="color: #800000;">dennis</span><span style="color: #800000;">"</span><span style="color: #000000;"><br />
p&nbsp;instance.name</span></div>
<br />
&nbsp;&nbsp;&nbsp;&nbsp;
instance通过OtherClass.new创建，但是此时(instance)还不存在，这与(OtherClass)情况不同，每个类一经创建就有一个metaclass，而对象就不一样，只有当你通过class&lt;&lt;instance 语法创建的时候，(instance)才被创建。注意test方法和name变量都将是instance对象特有的，类OtherClass并没有改变。观察下，发现(instance)继承于OtherClass，引出类的metaclass与对象的singleton类的又一个区别：类的metaclass继承自父类的metaclass，而对象的singleton类则是继承于对象的class。<br />
&nbsp;&nbsp;&nbsp; 那么当我们调用instance.class的时候，怎么不返回(instance)?这是c ruby在底层做了处理，instance的class在c ruby层次是(instance),当查找的时候忽略了singleton类以及下面将要谈到的include模块的代理类，沿着继承链上查找：<br />
86  VALUE<br />
87  rb_obj_class(obj)<br />
88      VALUE obj;<br />
89  {<br />
90      return rb_class_real(CLASS_OF(obj));<br />
91  }<br />
<br />
76  VALUE<br />
77  rb_class_real(cl)<br />
78      VALUE cl;<br />
79  {<br />
80      while (FL_TEST(cl, FL_SINGLETON) || TYPE(cl) == T_ICLASS) {<br />
81          cl = RCLASS(cl)-&gt;super;<br />
82      }<br />
83      return cl;<br />
84  }<br />
<br />
(object.c)<br />
<br />
核心代码就是：<br />
while (FL_TEST(cl, FL_SINGLETON) || TYPE(cl) == T_ICLASS) {<br />
&nbsp;
cl = RCLASS(cl)-&gt;super;<br />
&nbsp;}<br />
&nbsp;&nbsp;&nbsp; 其中FL_TEST(cl,FL_SINGLETON)用于测试是否是singleton类，而TYPE(cl)==TL_ICLASS是否是包含模块的代理类，TL_ICLASS的I就是include的意思。<br />
&nbsp;&nbsp;&nbsp; 图中类OtherClass继承Object，这个是显而易见的，不再多说。而Object、Class和Module这三个类是没办法通过API创建的，称为元类，他们的之间的关系如图所示，Object的class是Class,Module继承Object,而Class又继承Module，因此Class.kind_of? Object返回true,这个问题类似先有鸡，还是先有蛋的问题，是先有Object？还是先有Class?而c ruby的解决办法是不管谁先有，创建Object开始，接着创建Module和Class，然后分别创建它们的metaclass，从此整个Ruby的对象模型开始运转。<br />
<br />
1243  rb_cObject = boot_defclass("Object", 0);<br />
1244  rb_cModule = boot_defclass("Module", rb_cObject);<br />
1245  rb_cClass =  boot_defclass("Class",  rb_cModule);<br />
1246<br />
1247  metaclass = rb_make_metaclass(rb_cObject, rb_cClass);<br />
1248  metaclass = rb_make_metaclass(rb_cModule, metaclass);<br />
1249  metaclass = rb_make_metaclass(rb_cClass, metaclass);<br />
<br />
(object.c)<br />
<br />
那么当我们调用Class.class发生了什么？Class的klass其实指向的是(Class)，可根据上面的代码，我们知道会忽略这个(Class)，继续往上找就是(Module),同理找到(Object)，而(Object)继承自Class,显然Class的类仍然是Class，Class的类的类也是Class,多么有趣。同理，Object.class和Module.class都将是Class类。<br />
<br />
&nbsp;&nbsp;&nbsp; 再来看看include模块时发生的故事。include模块的过程如下图所示：<br />
<img src="http://www.blogjava.net/images/blogjava_net/killme2008/ch_class_include.png" alt="" border="0" /><br />
include模块，本质上是在对象或者类的klass和super之间插入了一个代理类iclass,这个代理类的方法表(m_table)和变量表(iv_table)分别指向了被包含的模块的方法表和变量表（通过指针，因此当包含的Module变化的时候，对象或者类也能相应变化），那么在查找类或者对象的class的时候，上面已经说明将忽略这些代理类。<br />
<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/149452.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-09-29 09:43 <a href="http://www.blogjava.net/killme2008/archive/2007/09/29/149452.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ruby变量在c ruby中的存储</title><link>http://www.blogjava.net/killme2008/archive/2007/09/20/146799.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Thu, 20 Sep 2007 08:17:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/09/20/146799.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/146799.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/09/20/146799.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/146799.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/146799.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 读完ruby hacking guide第6章，彻底总结下：<br />
1.在Ruby中，类也是一个对象，因此有实例变量。类的实例变量、类变量、常量都是存储在RClass struct的iv_tbl中，<br />
struct RClass {<br />
&nbsp;&nbsp;&nbsp; struct RBasic basic;<br />
&nbsp;&nbsp;&nbsp; struct st_table *iv_tbl;<br />
&nbsp;&nbsp;&nbsp; struct st_table *m_tbl;<br />
&nbsp;&nbsp;&nbsp; VALUE super;<br />
};<br />
iv_tbl的类型是st_table，我在<a href="http://www.blogjava.net/killme2008/archive/2007/09/18/146234.html">这里</a>用java实现了一下。<br />
<br />
2.用户自定义类的对象（ruby层次声明的类的对象)的实例变量存储在RObject struct的iv_tbl中，<br />
struct RObject {<br />
&nbsp; struct RBasic basic;<br />
&nbsp; struct st_table *iv_tbl;<br />
&nbsp;};<br />
调用方法，本质上是一个查表操作。buildin的几个类，比如String、Array、Hash等(在c层次上实现的类），它们的结构并没有iv_table，这是从节省内存空间的角度考虑，它们的实例变量存储在一张全局的st_table中。这张表比较特别，其中的每一个对应的值又是一个st_table，也就是一个&#8220;二元结构&#8221;，第一层结构是类名与实例变量表的映射，第二层才是实例变量名与实际值的映射。<br />
<br />
3.全局变量存储在一张全局的st_table中，这个表的键就是变量名ID，由于全局变量允许通过alias来设置别名，因此这张全局表中真正存储的是下面这个struct<br />
<br />
334  struct global_entry {<br />
335      struct global_variable *var;<br />
336      ID id;<br />
337  };<br />
<br />
324  struct global_variable {<br />
325      int   counter;      /* 引用计数 */<br />
326      void *data;         /* 变量值 */<br />
327      VALUE (*getter)();  /* 取值函数 */<br />
328      void  (*setter)();  /* 设置函数 */<br />
329      void  (*marker)();  /* 标记函数 */<br />
330      int block_trace;<br />
331      struct trace_var *trace;<br />
332  };<br />
(variable.c)<br />
<br />
当不同变量名（通过别名声明）指向的是同一个全局变量，其实它们指向的是同一个struct global_variable。<br />
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/146799.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-09-20 16:17 <a href="http://www.blogjava.net/killme2008/archive/2007/09/20/146799.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>深入下Ruby中的String</title><link>http://www.blogjava.net/killme2008/archive/2007/09/12/144417.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Wed, 12 Sep 2007 01:43:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/09/12/144417.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/144417.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/09/12/144417.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/144417.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/144417.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; Ruby语言中的String是mutable的，不像java、C#中的String是immutable的。比如<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str1="abc"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str2="abc"<br />
在java中，对于字面量的字符串，jvm内部维持一张表，因此如果在java中，str1和str2是同一个String对象。而在Ruby中，str1和str2是完全不同的对象。同样，在java中对于String对象的操作都将产生一个新的对象，而Ruby则是操纵同一个对象，比如:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str="abc"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str.concat("cdf")<br />
此时str就是"abccdf"。Ruby对String是怎么处理的呢？我们只谈谈c ruby中的实现，有兴趣的先看看这篇文章《<a href="http://dreamhead.blogbus.com/logs/3299713.html">管窥Ruby——对象基础</a>》。在ruby.h中我们可以看到String对象的结构，Ruby中的对象（包括类也是对象）都是一个一个的struct，String也不能例外：<br />
struct RString {<br />
&nbsp;&nbsp;&nbsp; struct RBasic basic;<br />
&nbsp;&nbsp;&nbsp; long len;<br />
&nbsp;&nbsp;&nbsp; char *ptr;<br />
&nbsp;&nbsp;&nbsp; union {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long capa;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VALUE shared;<br />
&nbsp;&nbsp;&nbsp; } aux;<br />
};<br />
//ruby.h<br />
<br />
&nbsp;&nbsp;&nbsp; 显然，len是String的长度；ptr是一个char类型的指针，指向实际的字符串；然后是一个联合，这个稍后再说。如果你看看ruby.h可以发现，几乎所有定义的对象结构都有一个struct RBasic。显然,struct RBasic包含由所有对象结构体共享的一些重要信息的。看看RBasic:<br />
<br />
struct RBasic {
<br />
&nbsp;unsigned long flags; <br />
&nbsp;VALUE klass; <br />
};<br />
其中的flags是一个多用途的标记，大多数情况下用于记录结构体的类型，ruby.h中预定义了一些列的宏，比如T_STRING（表示struct RString)，T_ARRAY(表示struct RArray）等。Klass是一个VALUE类型，VALUE也是unsigned long，可以地将它当成指针（一个指针4字节，绰绰有余了）,它指向的是一个Ruby对象，这里以后再深入。<br />
&nbsp;&nbsp;&nbsp; 那么联合aux中的capa和shared是干什么用的呢？因为Ruby的String是可变的，可变意味着len可以改变，我们需要每次都根据len的变换来增减内存（使用c中的realloc()函数），这显然是一个很大的开销，解决办法就是预留一定的空间，ptr指向的内存大小略大于len，这样就不需要频繁调用realloc了，aux.capa就是一个长度，包含额外的内存大小。那么aux.shared是干什么的呢？这是一个VALUE类型，说明它是指向某个对象。aux.shared其实是用于加快字符串的创建速度，在一个循环中：<br />
<pre>while true do  # 无限重复<br />
a = "str"        # 以&#8220;str&#8221;为内容创建字符串，赋值给a<br />
a.concat("ing")  # 为a所指向的对象添加&#8220;ing&#8221;<br />
p(a)             # 显示&#8220;string&#8221;<br />
end<br />
每次都重新创建一个"str"对象，内部就是重复创建一个char[],这是相当奢侈，aux.shared就是用于共享char[],<br />
以字面量创建的字符串会共享一个char[],当要发生变化时，将字符串复制到一个非共享的内存中，变化针对这<br />
个新拷贝进行，这就是所谓的&#8220;copy-on-write"技术。解释了String的内部构造，貌似还没有介绍String是怎么<br />
实现mutable，我们写一个Ruby扩展测试下，我们想写这样一个Ruby类：<br />
class Test<br />
def test<br />
str="str"<br />
str.concat("ing")<br />
end<br />
end<br />
对应的c语言代码就是：<br />
</pre>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">#include</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">stdio.h</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br />
#include&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;"><a title="" href="http://www.ruby-lang.org">ruby</a>.h</span><span style="color: #000000;">"</span><span style="color: #000000;"><br />
<br />
</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;VALUE&nbsp;t_test(VALUE&nbsp;self)<br />
{<br />
&nbsp;&nbsp;VALUE&nbsp;str;<br />
&nbsp;&nbsp;str</span><span style="color: #000000;">=</span><span style="color: #000000;">rb_str_new2(</span><span style="color: #000000;">"</span><span style="color: #000000;">str</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;printf(</span><span style="color: #000000;">"</span><span style="color: #000000;">before&nbsp;concat:&nbsp;str:%p,&nbsp;str.aux.shared:%p,&nbsp;str.ptr:%s</span><span style="color: #000000;">"</span><span style="color: #000000;">n</span><span style="color: #000000;">"</span><span style="color: #000000;">,str,</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(RSTRING(str)</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">aux).shared,RSTRING(str)</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">ptr);<br />
&nbsp;&nbsp;rb_str_cat2(str,</span><span style="color: #000000;">"</span><span style="color: #000000;">ing</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;printf(</span><span style="color: #000000;">"</span><span style="color: #000000;">after&nbsp;concat:&nbsp;str:%p,&nbsp;str.aux.shared:%p,&nbsp;str.ptr:%s</span><span style="color: #000000;">"</span><span style="color: #000000;">n</span><span style="color: #000000;">"</span><span style="color: #000000;">,</span><span style="color: #000000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;str,(RSTRING(str)</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">aux).shared,RSTRING(str)</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">ptr);<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;self;<br />
}<br />
VALUE&nbsp;cTest;<br />
</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;Init_string_hack(){<br />
&nbsp;&nbsp;cTest</span><span style="color: #000000;">=</span><span style="color: #000000;">rb_define_class(</span><span style="color: #000000;">"</span><span style="color: #000000;">Test</span><span style="color: #000000;">"</span><span style="color: #000000;">,rb_cObject);<br />
&nbsp;&nbsp;rb_define_method(cTest,</span><span style="color: #000000;">"</span><span style="color: #000000;">test</span><span style="color: #000000;">"</span><span style="color: #000000;">,t_test,</span><span style="color: #000000;">0</span><span style="color: #000000;">);<br />
<br />
}<br />
//string_hack.c<br />
</span></div>
<pre>   rb_define_class函数定义了一个类Test,rb_define_method将t_test方法以test的名称添加到Test类。在<br />
t_test中，通过rb_str_new2每次生成一个RString结构，然后通过rb_str_cat2将str与"ing"连接起来，添加<br />
了一些打印用于跟踪。利用mkmf产生Makefile,写一个extconf.rb<br />
require 'mkmf'<br />
create_makefile("string_hack");<br />
执行ruby extconf.rb，将产生一个Makefile,执行make，生成一个string_hack.so的链接库。扩展写完了，通过<br />
ruby调用：<br />
require 'string_hack"<br />
t=Test.new<br />
(1..3).each{|i| t.test}<br />
输出：<br />
before concat: str:0x40098a40, str.aux.shared:0x3, str.ptr:str<br />
after concat: str:0x40098a40, str.aux.shared:0x8, str.ptr:string<br />
before concat: str:0x40098a2c, str.aux.shared:0x3, str.ptr:str<br />
after concat: str:0x40098a2c, str.aux.shared:0x8, str.ptr:string<br />
before concat: str:0x40098a18, str.aux.shared:0x3, str.ptr:str<br />
after concat: str:0x40098a18, str.aux.shared:0x8, str.ptr:string<br />
从结果可以看出，在str concat之前之后，str指向的位置没有改变，改变的仅仅是str中ptr指向的字符串的值<br />
，看看rb_str_cat2函数的实现就一目了然了：<br />
VALUE rb_str_cat(str, ptr, len)<br />
&nbsp;&nbsp;&nbsp; VALUE str;<br />
&nbsp;&nbsp;&nbsp; const char *ptr;<br />
&nbsp;&nbsp;&nbsp; long len;<br />
{<br />
&nbsp;&nbsp;&nbsp; if (len &lt; 0) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rb_raise(rb_eArgError, "negative string size (or size too big)");<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; if (FL_TEST(str, STR_ASSOC)) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rb_str_modify(str);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; REALLOC_N(RSTRING(str)-&gt;ptr, char, RSTRING(str)-&gt;len+len);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; memcpy(RSTRING(str)-&gt;ptr + RSTRING(str)-&gt;len, ptr, len);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RSTRING(str)-&gt;len += len;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RSTRING(str)-&gt;ptr[RSTRING(str)-&gt;len] = '"0'; /* sentinel */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return str;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; return rb_str_buf_cat(str, ptr, len);<br />
}<br />
VALUE rb_str_cat2(str, ptr)<br />
&nbsp;&nbsp;&nbsp; VALUE str;<br />
&nbsp;&nbsp;&nbsp; const char *ptr;<br />
{<br />
&nbsp;&nbsp;&nbsp; return rb_str_cat(str, ptr, strlen(ptr));<br />
}<br />
//string.c<br />
<br />
</pre>
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/144417.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-09-12 09:43 <a href="http://www.blogjava.net/killme2008/archive/2007/09/12/144417.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ruby TK版本的google翻译机</title><link>http://www.blogjava.net/killme2008/archive/2007/09/04/142645.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Tue, 04 Sep 2007 07:55:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/09/04/142645.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/142645.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/09/04/142645.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/142645.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/142645.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 过去写的那个调用google翻译的翻译脚本，一直在用。那个版本只能处理单个单词，如果要翻译一行或者一段语句，尽管稍微修改下就可以，但失去了我想要的便利性。今天看了看TK，顺手写了个GUI版本的，采用一次请求一个线程，倒是便捷不少。在windows上，你需要到<a href="http://ruby.about.com/gi/dynamic/offsite.htm?zi=1/XJ&amp;sdn=ruby&amp;zu=http%3A%2F%2Faspn.activestate.com%2FASPN%2FDownloads%2FActiveTcl%2F">这里</a>下载安装ActiveTcl才可以运行。<br />
代码如下：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">require&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">net/http</span><span style="color: #800000;">'</span><span style="color: #000000;"><br />
require&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">tk</span><span style="color: #800000;">'</span><span style="color: #000000;"><br />
require&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">logger</span><span style="color: #800000;">'</span><span style="color: #000000;"><br />
</span><span style="color: #008000;">#</span><span style="color: #008000;">设置代理</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">$proxy_addr</span><span style="color: #000000;">=</span><span style="color: #800000;">'</span><span style="color: #800000;">x.x.x.x</span><span style="color: #800000;">'</span><span style="color: #000000;"><br />
$proxy_port</span><span style="color: #000000;">=</span><span style="color: #800000;">'</span><span style="color: #800000;">80</span><span style="color: #800000;">'</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;GoogleTranslate<br />
&nbsp; </span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;initialize(url)<br />
&nbsp;&nbsp;&nbsp;&nbsp;@log&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Logger.new(</span><span style="color: #800000;">"</span><span style="color: #800000;">translate.log</span><span style="color: #800000;">"</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;@log.level&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;Logger::WARN<br />
&nbsp;&nbsp;&nbsp;&nbsp;@url</span><span style="color: #000000;">=</span><span style="color: #000000;">url<br />
&nbsp;&nbsp;&nbsp;&nbsp;ph</span><span style="color: #000000;">=</span><span style="color: #000000;">{</span><span style="color: #800000;">'</span><span style="color: #800000;">padx</span><span style="color: #800000;">'</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">50</span><span style="color: #000000;">,</span><span style="color: #800000;">'</span><span style="color: #800000;">pady</span><span style="color: #800000;">'</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">10</span><span style="color: #000000;">}<br />
&nbsp;&nbsp;&nbsp;&nbsp;root</span><span style="color: #000000;">=</span><span style="color: #000000;">TkRoot.new{&nbsp;title&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">google&nbsp;翻译程序</span><span style="color: #800000;">'</span><span style="color: #000000;">}<br />
&nbsp;&nbsp;&nbsp;&nbsp;top</span><span style="color: #000000;">=</span><span style="color: #000000;">TkFrame.new(root)&nbsp;{background&nbsp;</span><span style="color: #800000;">"</span><span style="color: #800000;">white</span><span style="color: #800000;">"</span><span style="color: #000000;">}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">#</span><span style="color: #008000;">checkbutton，用于选择翻译类别</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;checked</span><span style="color: #000000;">=</span><span style="color: #000000;">TkVariable.new<br />
&nbsp;&nbsp;&nbsp;&nbsp;TkCheckButton.new(top)&nbsp;do<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;text&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">cn-en</span><span style="color: #800000;">'</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;variable&nbsp;checked<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pack({</span><span style="color: #800000;">'</span><span style="color: #800000;">padx</span><span style="color: #800000;">'</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">8</span><span style="color: #000000;">,</span><span style="color: #800000;">'</span><span style="color: #800000;">pady</span><span style="color: #800000;">'</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">10</span><span style="color: #000000;">})<br />
&nbsp;&nbsp;&nbsp;&nbsp;end&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;TkLabel.new(top){&nbsp;text&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">Enter&nbsp;text:</span><span style="color: #800000;">'</span><span style="color: #000000;">;pack(ph)}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;@text</span><span style="color: #000000;">=</span><span style="color: #000000;">TkVariable.new<br />
&nbsp;&nbsp;&nbsp;&nbsp;@result</span><span style="color: #000000;">=</span><span style="color: #000000;">TkVariable.new<br />
&nbsp;&nbsp;&nbsp;&nbsp;TkEntry.new(top,</span><span style="color: #800000;">'</span><span style="color: #800000;">textvariable</span><span style="color: #800000;">'</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">@text,</span><span style="color: #800000;">'</span><span style="color: #800000;">width</span><span style="color: #800000;">'</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">40</span><span style="color: #000000;">).pack(ph)<br />
&nbsp;&nbsp;&nbsp;&nbsp;pig_b</span><span style="color: #000000;">=</span><span style="color: #000000;">TkButton.new(top){text&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">翻译</span><span style="color: #800000;">'</span><span style="color: #000000;">;pack&nbsp;ph}<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">#</span><span style="color: #008000;">翻译按钮事件</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;pig_b.command{&nbsp;translate(checked.value)&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;TkLabel.new(top){&nbsp;text&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">Translate&nbsp;Result:</span><span style="color: #800000;">'</span><span style="color: #000000;">;pack(ph)}<br />
&nbsp;&nbsp;&nbsp;&nbsp;TkEntry.new(top,</span><span style="color: #800000;">'</span><span style="color: #800000;">textvariable</span><span style="color: #800000;">'</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">@result,</span><span style="color: #800000;">'</span><span style="color: #800000;">width</span><span style="color: #800000;">'</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">40</span><span style="color: #000000;">).pack(ph)<br />
&nbsp;&nbsp;&nbsp;&nbsp;pig_a</span><span style="color: #000000;">=</span><span style="color: #000000;">TkButton.new(top)&nbsp;do<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;text&nbsp;</span><span style="color: #800000;">'</span><span style="color: #800000;">Exit</span><span style="color: #800000;">'</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pack&nbsp;ph<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;command&nbsp;{exit}<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;top.pack(</span><span style="color: #800000;">'</span><span style="color: #800000;">fill</span><span style="color: #800000;">'</span><span style="color: #000000;">=&gt;</span><span style="color: #800000;">'</span><span style="color: #800000;">both</span><span style="color: #800000;">'</span><span style="color: #000000;">,</span><span style="color: #800000;">'</span><span style="color: #800000;">side</span><span style="color: #800000;">'</span><span style="color: #000000;">=&gt;</span><span style="color: #800000;">'</span><span style="color: #800000;">top</span><span style="color: #800000;">'</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;end<br />
&nbsp;&nbsp;</span><span style="color: #0000ff;">def</span><span style="color: #000000;">&nbsp;translate(checked)<br />
&nbsp;&nbsp;&nbsp;&nbsp;langpair</span><span style="color: #000000;">=</span><span style="color: #800000;">'</span><span style="color: #800000;">en|zh-CN</span><span style="color: #800000;">'</span><span style="color: #000000;">&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;langpair</span><span style="color: #000000;">=</span><span style="color: #800000;">'</span><span style="color: #800000;">zh-CN|en</span><span style="color: #800000;">'</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;checked</span><span style="color: #000000;">==</span><span style="color: #800000;">'</span><span style="color: #800000;">1</span><span style="color: #800000;">'</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">#</span><span style="color: #008000;">开一个新线程处理</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;Thread.new&nbsp;do<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;begin<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response</span><span style="color: #000000;">=</span><span style="color: #000000;">Net::HTTP.Proxy($proxy_addr,$proxy_port).post_form(URI.parse(@url),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</span><span style="color: #800000;">'</span><span style="color: #800000;">text</span><span style="color: #800000;">'</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">@text.value,</span><span style="color: #800000;">'</span><span style="color: #800000;">langpair</span><span style="color: #800000;">'</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">langpair})<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response.body&nbsp;</span><span style="color: #000000;">=~</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">/&lt;</span><span style="color: #000000;">div&nbsp;id</span><span style="color: #000000;">=</span><span style="color: #000000;">result_box&nbsp;dir</span><span style="color: #000000;">=</span><span style="color: #000000;">ltr</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">(.</span><span style="color: #000000;">*</span><span style="color: #000000;">?)</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">\</span><span style="color: #000000;">/</span><span style="color: #000000;">div</span><span style="color: #000000;">&gt;/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@result.value</span><span style="color: #000000;">=</span><span style="color: #000000;">$</span><span style="color: #000000;">1</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rescue&nbsp;Exception</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">e<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@log.error(e)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;end<br />
end<br />
GoogleTranslate.new(</span><span style="color: #800000;">"</span><span style="color: #800000;">http://translate.google.com/translate_t</span><span style="color: #800000;">"</span><span style="color: #000000;">)<br />
Tk.mainloop</span></div>
<br />
<br /><img src ="http://www.blogjava.net/killme2008/aggbug/142645.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-09-04 15:55 <a href="http://www.blogjava.net/killme2008/archive/2007/09/04/142645.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>rubylearning.com推出新的免费教程</title><link>http://www.blogjava.net/killme2008/archive/2007/08/31/141602.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Fri, 31 Aug 2007 01:06:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/08/31/141602.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/141602.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/08/31/141602.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/141602.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/141602.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 在<a href="http://www.infoq.com/cn/news/2007/08/rubylearning-online-tutorial">infoq</a>上看到这个消息，想了解ruby的不妨从<a href="http://rubylearning.com/satishtalim/tutorial.html">这份教程</a>开始，初略看了下目录，内容还是挺全的，该介绍的都介绍到了。我自己准备将<strong>Advanced <a title="" href="http://www.ruby-lang.org" >ruby</a></strong>部分读一下，也算是练手，想掌握任何一门编程语言，每天至少都得写上那么几段代码保持&#8220;手感&#8221;，HOHO。一天一个主题，利用业余时间和工作间隙花上两个星期就够了。<img src ="http://www.blogjava.net/killme2008/aggbug/141602.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-08-31 09:06 <a href="http://www.blogjava.net/killme2008/archive/2007/08/31/141602.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>从一个小例子出发之ruby、scheme和Erlang的简单比较</title><link>http://www.blogjava.net/killme2008/archive/2007/07/15/130384.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Sun, 15 Jul 2007 08:11:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/07/15/130384.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/130384.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/07/15/130384.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/130384.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/130384.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; Lich Ray写了个帖子《<a href="http://www.javaeye.com/post/333938">函数式编程语言曲高和寡？</a>》，用快速排序的例子来说明函数式编程在表达思想方面比命令式语言更容易，其实这一点毋庸置疑，如果你正在读或者读过SICP的话。文中给了haskell、scheme和javascript的实现例子，我也凑趣写了个Erlang版本，haskell我不了解就不说了，其他实现分别如下：<br>scheme：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">(define&nbsp;(qsort&nbsp;ls)&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(null</span><span style="color: #000000;">?</span><span style="color: #000000;">&nbsp;ls)&nbsp;</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">()&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((x&nbsp;(car&nbsp;ls))&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(xs&nbsp;(cdr&nbsp;ls)))&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(let&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((lt&nbsp;(filter&nbsp;(lambda&nbsp;(y)&nbsp;(&lt;&nbsp;y&nbsp;x))&nbsp;xs))&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(st&nbsp;(filter&nbsp;(lambda&nbsp;(y)&nbsp;(&gt;=&nbsp;y&nbsp;x))&nbsp;xs)))&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(append&nbsp;(qsort&nbsp;lt)&nbsp;(list&nbsp;x)&nbsp;(qsort&nbsp;st))))))&nbsp;&nbsp;</span></div>
<br>javascript:<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">//</span><span style="color: #000000;">&nbsp;把要用到的表达式抽象出来&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;Array</span><span style="color: #000000;">.</span><span style="color: #0000ff;">prototype</span><span style="color: #000000;">.</span><span style="color: #000000;">head&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;function&nbsp;()&nbsp;{&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;this[</span><span style="color: #800000;">0</span><span style="color: #000000;">];&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;Array</span><span style="color: #000000;">.</span><span style="color: #0000ff;">prototype</span><span style="color: #000000;">.</span><span style="color: #000000;">tail&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;function&nbsp;()&nbsp;{&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;this</span><span style="color: #000000;">.</span><span style="color: #000000;">slice(</span><span style="color: #800000;">1</span><span style="color: #000000;">);&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;Array</span><span style="color: #000000;">.</span><span style="color: #0000ff;">prototype</span><span style="color: #000000;">.</span><span style="color: #000000;">filter&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;function&nbsp;(proc)&nbsp;{&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;tmpArr&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;[];&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;(var&nbsp;i&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #800000;">0</span><span style="color: #000000;">;&nbsp;i&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;this</span><span style="color: #000000;">.</span><span style="color: #0000ff;">length</span><span style="color: #000000;">;&nbsp;i</span><span style="color: #000000;">++</span><span style="color: #000000;">)&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(proc(this[i])&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;true)&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tmpArr</span><span style="color: #000000;">.</span><span style="color: #0000ff;">push</span><span style="color: #000000;">(this[i]);&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;tmpArr;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;Array</span><span style="color: #000000;">.</span><span style="color: #0000ff;">prototype</span><span style="color: #000000;">.</span><span style="color: #000000;">qsort&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;function&nbsp;()&nbsp;{&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;(this&nbsp;</span><span style="color: #000000;">==</span><span style="color: #000000;">&nbsp;false)&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;[]&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;x</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;xs</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;lt</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;st&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;this</span><span style="color: #000000;">.</span><span style="color: #000000;">head()&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xs&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;this</span><span style="color: #000000;">.</span><span style="color: #000000;">tail()&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lt&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;xs</span><span style="color: #000000;">.</span><span style="color: #000000;">filter(function&nbsp;(y)&nbsp;{</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;y&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;x})&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;st&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;xs</span><span style="color: #000000;">.</span><span style="color: #000000;">filter(function&nbsp;(y)&nbsp;{</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;y&nbsp;</span><span style="color: #000000;">&gt;=</span><span style="color: #000000;">&nbsp;x})&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;lt</span><span style="color: #000000;">.</span><span style="color: #000000;">qsort()</span><span style="color: #000000;">.</span><span style="color: #000000;">concat([x]</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;st</span><span style="color: #000000;">.</span><span style="color: #000000;">qsort())&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></div>
用Erlang的话，Erlang的list其实跟scheme的list是一样的，甚至连定义的基本高阶函数都一样：map,filter，append等等,利用lists模块提供的filter和append，我们可以写出：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;qsort([])</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">[];&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;qsort([H</span><span style="color: #000000;">|</span><span style="color: #000000;">T])</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Lt</span><span style="color: #000000;">=</span><span style="color: #000000;">lists</span><span style="color: #000000;">:</span><span style="color: #000000;">filter(fun(E)</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">E</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">H&nbsp;end</span><span style="color: #000000;">,</span><span style="color: #000000;">T)</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;St</span><span style="color: #000000;">=</span><span style="color: #000000;">lists</span><span style="color: #000000;">:</span><span style="color: #000000;">filter(fun(E)</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">E</span><span style="color: #000000;">&gt;=</span><span style="color: #000000;">H&nbsp;end</span><span style="color: #000000;">,</span><span style="color: #000000;">T)</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;lists</span><span style="color: #000000;">:</span><span style="color: #000000;">append(qsort(Lt)</span><span style="color: #000000;">,</span><span style="color: #000000;">lists</span><span style="color: #000000;">:</span><span style="color: #000000;">append([H]</span><span style="color: #000000;">,</span><span style="color: #000000;">qsort(St)))</span><span style="color: #000000;">.</span><span style="color: #000000;">&nbsp;&nbsp;</span></div>
&nbsp; &nbsp; 我们来比较下scheme和Erlang版本，两者最显著的不同是，scheme使用了条件语句if，而Erlang却是通过模式匹配来代替条件分支判断。同样，在list的分解上面，Erlang也是利用了规则匹配来代替car,cdr函数，从这里可以看出规则匹配在Erlang中的主要作用：分解复杂数据结构以便赋值和条件分支的分派。<br>&nbsp;&nbsp;&nbsp; 扯远些可以谈到模式匹配是以&#8220;like-a&#8221;来代替消息分派在传统命令式语言中严格的&#8220;is-a&#8221;，这也跟现实世界的情况更为符合，现实世界中我们对事物的判断都是模糊。而这一点，不正是&#8220;Duck-Typing&#8221;？传统语言对于对象的类型(type)判断来源于严格确定对象是什么类（class），不是这个类它就没有相应的方法，而事实上类与类型这两个概念并不是一致的，对象的类型更应该根据对象能够做什么来决定。扯远了，这只是我读《<a href="http://www.javaeye.com/topic/25649">失踪的链环</a>》得来的感受，如果对模式匹配还有怀疑的话，让我们回到这个例子的Erlang版本，代码中我们调用了两次filter进行全表扫描，以便得到根据H切割的大小两个部分，这在性能上有不小的影响，那么我们能不能只进行一次全表扫描呢，返回结果是&#8220;大小&#8221;两个部分，看看Erlang应该怎么写：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;"></span><span style="color: #000000;"></span><span style="color: #000000;"></span><span style="color: #0000ff;">sort([]) -&gt; [];<br>sort([Pivot|Rest]) -&gt;<br>&nbsp;&nbsp; {Smaller, Bigger} = split(Pivot, Rest),<br>&nbsp;&nbsp; lists:append(sort(Smaller), [Pivot|sort(Bigger)]).
<br>split</span><span style="color: #000000;">(Pivot</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;L)&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">split</span><span style="color: #000000;">(Pivot</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;L</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;[]</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;[])</span><span style="color: #000000;">.</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">split</span><span style="color: #000000;">(Pivot</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;[]</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;Smaller</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;Bigger)&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;"><br>{Smaller</span><span style="color: #000000;">,</span><span style="color: #000000;">Bigger};<br></span><span style="color: #0000ff;">split</span><span style="color: #000000;">(Pivot</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;[H</span><span style="color: #000000;">|</span><span style="color: #000000;">T]</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;Smaller</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;Bigger)&nbsp;when&nbsp;H&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;Pivot&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">split</span><span style="color: #000000;">(Pivot</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;T</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;[H</span><span style="color: #000000;">|</span><span style="color: #000000;">Smaller]</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;Bigger);<br></span><span style="color: #0000ff;">split</span><span style="color: #000000;">(Pivot</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;[H</span><span style="color: #000000;">|</span><span style="color: #000000;">T]</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;Smaller</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;Bigger)&nbsp;when&nbsp;H&nbsp;</span><span style="color: #000000;">&gt;=</span><span style="color: #000000;">&nbsp;Pivot&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">split</span><span style="color: #000000;">(Pivot</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;T</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;Smaller</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;[H</span><span style="color: #000000;">|</span><span style="color: #000000;">Bigger])</span><span style="color: #000000;">.</span></div>
<br>&nbsp;&nbsp;&nbsp; 这几行代码充分展现了模式匹配的威力，不过Erlang其实有内置的方法partition用于切割list的，这里只是为了展现模式匹配，因此上面的代码可以改为：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">sort</span><span style="color: #000000;">([])&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">&nbsp;[];<br></span><span style="color: #0000ff;">sort</span><span style="color: #000000;">([Pivot</span><span style="color: #000000;">|</span><span style="color: #000000;">Rest])&nbsp;</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;"><br>{Smaller</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;Bigger}&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;lists</span><span style="color: #000000;">:</span><span style="color: #000000;">partition(fun(E)</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">E</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">Pivot&nbsp;end</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;Rest)</span><span style="color: #000000;">,</span><span style="color: #000000;"><br>lists</span><span style="color: #000000;">:</span><span style="color: #000000;">append(</span><span style="color: #0000ff;">sort</span><span style="color: #000000;">(Smaller)</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;[Pivot</span><span style="color: #000000;">|</span><span style="color: #0000ff;">sort</span><span style="color: #000000;">(Bigger)])</span><span style="color: #000000;">.</span></div>
<br>同样的代码改写为ruby版本：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">def&nbsp;qsort(array)<br>&nbsp; arr=array.dup<br>&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;arr</span><span style="color: #000000;">==</span><span style="color: #000000;">[]<br>&nbsp;&nbsp;&nbsp;&nbsp;[]<br>&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;x</span><span style="color: #000000;">=</span><span style="color: #000000;">arr</span><span style="color: #000000;">.</span><span style="color: #0000ff;">shift</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;smaller</span><span style="color: #000000;">,</span><span style="color: #000000;">bigger</span><span style="color: #000000;">=</span><span style="color: #000000;">arr</span><span style="color: #000000;">.</span><span style="color: #000000;">partition{</span><span style="color: #000000;">|</span><span style="color: #000000;">e</span><span style="color: #000000;">|</span><span style="color: #000000;">&nbsp;e</span><span style="color: #000000;">&lt;=</span><span style="color: #000000;">x}<br>&nbsp;&nbsp;&nbsp;&nbsp;qsort(smaller)</span><span style="color: #000000;">+</span><span style="color: #000000;">[x]</span><span style="color: #000000;">+</span><span style="color: #000000;">qsort(bigger)<br>&nbsp;&nbsp;end<br>end</span></div>
&nbsp;&nbsp;&nbsp; ruby与Erlang都有并行赋值，但是ruby不支持模式匹配。请注意ruby并没有尾递归优化，因此上面的代码在数组比较大的时候会导致栈溢出，想用ruby做函数式编程应该尽量多使用循环和map,filter,collect等辅助高阶函数。<br>&nbsp;&nbsp;&nbsp; 另外一个Erlang与ruby、scheme比较重要的区别是Erlang的变量只能赋值一次（或者说绑定），也就是single assignment。这个特点与Erlang所要满足的运行场景有紧密关系，当系统发生错误时，就可以从原来的值重新启动任务，而不用担心由于变量值的变化导致系统恢复困难。<br><br><br><br><br><img src ="http://www.blogjava.net/killme2008/aggbug/130384.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-07-15 16:11 <a href="http://www.blogjava.net/killme2008/archive/2007/07/15/130384.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>改了下rss-reader，支持atom了</title><link>http://www.blogjava.net/killme2008/archive/2007/07/11/129651.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Wed, 11 Jul 2007 08:50:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/07/11/129651.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/129651.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/07/11/129651.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/129651.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/129651.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 发现gigix新的blog是支持atom的，也让这个<a  href="http://www.blogjava.net/killme2008/archive/2007/07/09/129047.html">小工具</a>支持下atom，去rubyforge找了圈，有个叫atom的lib简单易用，就选他了。<br>&nbsp;&nbsp;&nbsp; 首先，gem install atom，安装一下<br>&nbsp;&nbsp;&nbsp; 其次，稍微修改下代码：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">def&nbsp;blog_info(url)<br>&nbsp;&nbsp;str</span><span style="color: #000000;">=</span><span style="color: #0000ff;">open</span><span style="color: #000000;">(url)</span><span style="color: #000000;">.</span><span style="color: #0000ff;">read</span><span style="color: #000000;"><br>&nbsp;&nbsp;feed&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;RSS</span><span style="color: #000000;">::</span><span style="color: #000000;">Parser</span><span style="color: #000000;">.</span><span style="color: #000000;">parse(str</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;false)<br>&nbsp;&nbsp;</span><span style="color: #0000ff;">unless</span><span style="color: #000000;">&nbsp;feed<br>&nbsp;&nbsp;&nbsp;&nbsp;feed</span><span style="color: #000000;">=</span><span style="color: #000000;">Atom</span><span style="color: #000000;">::</span><span style="color: #000000;">Feed</span><span style="color: #000000;">.</span><span style="color: #000000;">new(str)<br>&nbsp;&nbsp;&nbsp;&nbsp;blog</span><span style="color: #000000;">=</span><span style="color: #000000;">Blog</span><span style="color: #000000;">.</span><span style="color: #000000;">new(feed</span><span style="color: #000000;">.</span><span style="color: #000000;">title</span><span style="color: #000000;">,</span><span style="color: #000000;">url</span><span style="color: #000000;">,</span><span style="color: #000000;">feed</span><span style="color: #000000;">.</span><span style="color: #000000;">entries)<br>&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp; blog</span><span style="color: #000000;">=</span><span style="color: #000000;">Blog</span><span style="color: #000000;">.</span><span style="color: #000000;">new(feed</span><span style="color: #000000;">.</span><span style="color: #000000;">channel</span><span style="color: #000000;">.</span><span style="color: #000000;">title</span><span style="color: #000000;">,</span><span style="color: #000000;">url</span><span style="color: #000000;">,</span><span style="color: #000000;">feed</span><span style="color: #000000;">.</span><span style="color: #000000;">items)<br>&nbsp;&nbsp;end<br>end</span></div>
先尝试用RSS模块去读，失败的话就用Atom模块，运行下，问题出来了，这个atom lib的entries数组中是一个一个的Atom:Entry对象，而这个Entry类并没有我在模板文件中定义的link，取而代之的是一个links数组，links数组中的Link对象href属性才是我想要的，那么，修改模板文件？或者修改atom lib的源码？No,No，都不用，ruby天然的open class特性让你随心所欲，我们打开Atom:Entry类，给它添加个link方法就OK：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">class&nbsp;Atom</span><span style="color: #000000;">::</span><span style="color: #000000;">Entry<br>&nbsp;&nbsp;def&nbsp;</span><span style="color: #0000ff;">link</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;links[</span><span style="color: #800000;">0</span><span style="color: #000000;">]</span><span style="color: #000000;">.</span><span style="color: #000000;">href<br>&nbsp;&nbsp;end<br>end</span></div>
这样一来，模板文件也不用改了，更不用去修改atom lib的源码，实在是够爽，现在完整的rss-reader是这样：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">require</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">rss/2.0</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">require</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">open-uri</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">require</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">erb</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">require</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">atom</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;"><br></span><span style="color: #008000;">#</span><span style="color: #008000;">&nbsp;author&nbsp;dennis<br>#&nbsp;email&nbsp;killme2008@gmail.com</span><span style="color: #008000;"><br></span><span style="color: #000000;">class&nbsp;Atom</span><span style="color: #000000;">::</span><span style="color: #000000;">Entry<br>&nbsp;&nbsp;def&nbsp;</span><span style="color: #0000ff;">link</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;links[</span><span style="color: #800000;">0</span><span style="color: #000000;">]</span><span style="color: #000000;">.</span><span style="color: #000000;">href<br>&nbsp;&nbsp;end<br>end<br>class&nbsp;Blog<br>&nbsp;&nbsp;attr_accessor</span><span style="color: #000000;">:</span><span style="color: #000000;">title</span><span style="color: #000000;">,:</span><span style="color: #000000;">url</span><span style="color: #000000;">,:</span><span style="color: #000000;">items<br>&nbsp;&nbsp;def&nbsp;initialize(title</span><span style="color: #000000;">,</span><span style="color: #000000;">url</span><span style="color: #000000;">,</span><span style="color: #000000;">items</span><span style="color: #000000;">=</span><span style="color: #000000;">[])<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800080;">@title</span><span style="color: #000000;">=</span><span style="color: #000000;">title<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800080;">@url</span><span style="color: #000000;">=</span><span style="color: #000000;">url<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800080;">@items</span><span style="color: #000000;">=</span><span style="color: #000000;">items<br>&nbsp;&nbsp;end<br>end<br>def&nbsp;blog_info(url)<br>&nbsp;&nbsp;str</span><span style="color: #000000;">=</span><span style="color: #0000ff;">open</span><span style="color: #000000;">(url)</span><span style="color: #000000;">.</span><span style="color: #0000ff;">read</span><span style="color: #000000;"><br>&nbsp;&nbsp;feed&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;RSS</span><span style="color: #000000;">::</span><span style="color: #000000;">Parser</span><span style="color: #000000;">.</span><span style="color: #000000;">parse(str</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;false)<br>&nbsp;&nbsp;</span><span style="color: #0000ff;">unless</span><span style="color: #000000;">&nbsp;feed<br>&nbsp;&nbsp;&nbsp;&nbsp;feed</span><span style="color: #000000;">=</span><span style="color: #000000;">Atom</span><span style="color: #000000;">::</span><span style="color: #000000;">Feed</span><span style="color: #000000;">.</span><span style="color: #000000;">new(str)<br>&nbsp;&nbsp;&nbsp;&nbsp;blog</span><span style="color: #000000;">=</span><span style="color: #000000;">Blog</span><span style="color: #000000;">.</span><span style="color: #000000;">new(feed</span><span style="color: #000000;">.</span><span style="color: #000000;">title</span><span style="color: #000000;">,</span><span style="color: #000000;">url</span><span style="color: #000000;">,</span><span style="color: #000000;">feed</span><span style="color: #000000;">.</span><span style="color: #000000;">entries)<br>&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;blog</span><span style="color: #000000;">=</span><span style="color: #000000;">Blog</span><span style="color: #000000;">.</span><span style="color: #000000;">new(feed</span><span style="color: #000000;">.</span><span style="color: #000000;">channel</span><span style="color: #000000;">.</span><span style="color: #000000;">title</span><span style="color: #000000;">,</span><span style="color: #000000;">url</span><span style="color: #000000;">,</span><span style="color: #000000;">feed</span><span style="color: #000000;">.</span><span style="color: #000000;">items)<br>&nbsp;&nbsp;end<br>end<br>def&nbsp;rss_read<br>&nbsp;&nbsp;urls</span><span style="color: #000000;">=</span><span style="color: #000000;">[</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">http://www.blogjava.net/canonical/rss</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;">,</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">http://dreamhead.blogbus.com/index.rdf</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;">,</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">http://michael.nona.name/rss</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;">,</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">http://blog.csdn.net/mozilla/Rss.aspx</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;">,</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">http://blog.csdn.net/g9yuayon/Rss.aspx</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;">]<br>&nbsp;&nbsp;urls</span><span style="color: #000000;">.</span><span style="color: #000000;">collect&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">|</span><span style="color: #000000;">blog_url</span><span style="color: #000000;">|</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;blog_info(blog_url)<br>&nbsp;&nbsp;end&nbsp;&nbsp;<br>end<br></span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;$</span><span style="color: #800000;">0</span><span style="color: #000000;">==</span><span style="color: #0000ff;">__FILE__</span><span style="color: #000000;"><br>&nbsp;&nbsp;blogs</span><span style="color: #000000;">=</span><span style="color: #000000;">rss_read()<br>&nbsp;&nbsp;</span><span style="color: #008000;">#</span><span style="color: #008000;">读取模板文件</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;template</span><span style="color: #000000;">=</span><span style="color: #000000;">IO</span><span style="color: #000000;">.</span><span style="color: #0000ff;">read</span><span style="color: #000000;">(File</span><span style="color: #000000;">.</span><span style="color: #000000;">dirname(</span><span style="color: #0000ff;">__FILE__</span><span style="color: #000000;">)</span><span style="color: #000000;">+</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">/blogs.html</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">)<br>&nbsp;&nbsp;message</span><span style="color: #000000;">=</span><span style="color: #000000;">ERB</span><span style="color: #000000;">.</span><span style="color: #000000;">new(template)<br>&nbsp;&nbsp;</span><span style="color: #008000;">#</span><span style="color: #008000;">输出结果文件</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;File</span><span style="color: #000000;">.</span><span style="color: #0000ff;">open</span><span style="color: #000000;">(</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">today.html</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">,</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">w+</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">){</span><span style="color: #000000;">|</span><span style="color: #000000;">file</span><span style="color: #000000;">|</span><span style="color: #000000;">&nbsp;file</span><span style="color: #000000;">.</span><span style="color: #000000;">puts&nbsp;message</span><span style="color: #000000;">.</span><span style="color: #000000;">result}<br>end<br></span></div>
<br><br><img src ="http://www.blogjava.net/killme2008/aggbug/129651.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-07-11 16:50 <a href="http://www.blogjava.net/killme2008/archive/2007/07/11/129651.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>让ruby简化你的工作之blog阅读器</title><link>http://www.blogjava.net/killme2008/archive/2007/07/09/129047.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Mon, 09 Jul 2007 07:14:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/07/09/129047.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/129047.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/07/09/129047.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/129047.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/129047.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 阅读专家和牛人的blog已经是我学习的一种主要方法之一，我每天的必做的就是关注下dreamhead、gigix、江南白衣、robbin、李锟等牛人的blog是不是有什么新文章。不过我非常讨厌安装商业公司的rss阅读器，我害怕他们是流氓软件！而且很多阅读器的文章格式与原文有较大差异从而导致重要信息的丢失，我还是喜欢用firefox畅游网络，这导致我不得不一次一次地在各个blog间跳转，打开n个网页查找我关注的信息，一次两次也就罢了，天天这样实在是太麻烦了，那么，有没有什么工具来简化我的工作，他能自动每天把我关注的所有blog的文章放在一个页面里，我每天早上需要做的只是运行下这个工具，然后打开生成的网页就可以看到牛人们的blog。甚至，我可以在windows下做个计划任务或者linux下使用cron让这个工具每天在夜深人静的时候自动运行下，那我每天早上就可以看到牛人们新鲜出炉的好文章了。这个工具生成的网页应该类似下面这样：<br><span style="font-weight: bold;"></span><img src="http://www.blogjava.net/images/blogjava_net/killme2008/blog1.gif" border="0"><br>然后，当我点击某个blog标题的时候会自动展开文章列表：<br><img src="http://www.blogjava.net/images/blogjava_net/killme2008/blog2.gif" border="0"><br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 点击文章标题就会跳转到相应的文章网页。OK,想好了需求，怎么做？写这样的东西当然是脚本语言最快了，我们用ruby来完成这个工具脚本。稍微思考下就可以知道大概的思路，应该是通过某个方法连接到各个blog站点，然后抓取我们需要的信息集中显示在这个页面里。也许你还想到要用正则表达式去解析网页内容等等，可想象一下这个工作量将多大，再说现在的blog都有替换模板功能，如果哪天换了模板，正则匹配就失效了，还得重新再来，这也太麻烦了。幸好，blog都有提供RSS啊，我们根本没必要那么麻烦，直接读RSS不就可以了？那么ruby有没有提供读rss的API？还是要我们自己去解析xml？这件事问下《ruby cookbook》就OK。ruby有提供一个解析rss的库，支持rss0.9,1.0和2.0标准，权衡之下，我使用了rss2.0，后来发现也可以正常读取rss1.0的blog。开始写我们的脚本，先建立一个Blog类用于存放信息：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">class&nbsp;Blog<br>&nbsp;&nbsp;attr_accessor</span><span style="color: #000000;">:</span><span style="color: #000000;">title</span><span style="color: #000000;">,:</span><span style="color: #000000;">url</span><span style="color: #000000;">,:</span><span style="color: #000000;">items<br>&nbsp;&nbsp;def&nbsp;initialize(title</span><span style="color: #000000;">,</span><span style="color: #000000;">url</span><span style="color: #000000;">,</span><span style="color: #000000;">items</span><span style="color: #000000;">=</span><span style="color: #000000;">[])<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800080;">@title</span><span style="color: #000000;">=</span><span style="color: #000000;">title<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800080;">@url</span><span style="color: #000000;">=</span><span style="color: #000000;">url<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800080;">@items</span><span style="color: #000000;">=</span><span style="color: #000000;">items<br>&nbsp;&nbsp;end<br>end</span></div>
&nbsp;&nbsp;&nbsp; title、url和items分别是blog的标题、地址和文章列表，我们将文章存储在一个数组里,默认是空的。然后再定义一个解析blog信息的方法blog_info，根据地址连接rss源并返回一个Blog对象：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">def&nbsp;blog_info(url)<br>&nbsp;&nbsp;feed&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;RSS</span><span style="color: #000000;">::</span><span style="color: #000000;">Parser</span><span style="color: #000000;">.</span><span style="color: #000000;">parse(</span><span style="color: #0000ff;">open</span><span style="color: #000000;">(url)</span><span style="color: #000000;">.</span><span style="color: #0000ff;">read</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;false)&nbsp;<br>&nbsp;&nbsp;blog</span><span style="color: #000000;">=</span><span style="color: #000000;">Blog</span><span style="color: #000000;">.</span><span style="color: #000000;">new(feed</span><span style="color: #000000;">.</span><span style="color: #000000;">channel</span><span style="color: #000000;">.</span><span style="color: #000000;">title</span><span style="color: #000000;">,</span><span style="color: #000000;">url</span><span style="color: #000000;">,</span><span style="color: #000000;">feed</span><span style="color: #000000;">.</span><span style="color: #000000;">items)<br>end</span></div>
&nbsp;&nbsp;&nbsp; 注意，ruby方法默认返回的最后一行的运行结果，这里就是new的Blog对象,我们通过open-uri库的open方法连接地址并读取内容，然后使用RSS模块的Parser类解析信息，最后将这些信息组织成一个Blog对象并返回。我同时关注好几个blog，那么将这些blog的rss地址放在一个数组里，然后遍历数组分别调用blog_info得到Blog对象，最后需要考虑的就是怎么将Blog对象显示在网页里。<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">def&nbsp;rss_read<br>&nbsp;&nbsp;urls</span><span style="color: #000000;">=</span><span style="color: #000000;">[</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">http://www.blogjava.net/canonical/rss</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;">,</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">http://dreamhead.blogbus.com/index.rdf</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;">,</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">http://michael.nona.name/rss</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;">,</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">http://blog.csdn.net/mozilla/Rss.aspx</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;">,</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">http://blog.csdn.net/g9yuayon/Rss.aspx</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;">]<br></span><span style="color: #000000;"></span><span style="color: #000000;">&nbsp; urls</span><span style="color: #000000;">.</span><span style="color: #0000ff;">collect</span><span style="color: #000000;"> </span><span style="color: #0000ff;">do</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">|</span><span style="color: #000000;">blog_url</span><span style="color: #000000;">|</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;blogs</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">blog_info(blog_url)<br>&nbsp;&nbsp;end&nbsp;&nbsp;<br>end</span></div>
&nbsp;&nbsp;&nbsp; rss_read方法最后返回Blog对象组成的数组，剩下的任务就是将这个数组里信息显示在生成的网页里。这个问题很类似生成静态html文件的需求，那么ruby是否有类似freemark的模板语言？答案当然是yes，ruby on rails使用了ERb将ruby代码嵌入模板当中，我们当然也可以这样做。ERb类似jsp的语法,&lt;%=name%&gt;就是输出变量name,&lt;% %&gt;中的代码就是一般的ruby代码，因此，首先定义我们的模板文件blogs.html<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;"><br></span><span style="color: #000000;">&lt;</span><span style="color: #000000;">html</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">head</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">title</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">simple&nbsp;rss&nbsp;reader</span><span style="color: #000000;">&lt;/</span><span style="color: #000000;">title</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">meta&nbsp;http</span><span style="color: #000000;">-</span><span style="color: #000000;">equiv</span><span style="color: #000000;">=</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">Content-Type</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">&nbsp;content</span><span style="color: #000000;">=</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">text/html;&nbsp;charset=UTF-8</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">style&nbsp;rel</span><span style="color: #000000;">=</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">stylesheet</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">&nbsp;type</span><span style="color: #000000;">=</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">text/css</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">&nbsp;media</span><span style="color: #000000;">=</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">all</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">/&gt;</span><span style="color: #000000;">body&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;margin</span><span style="color: #000000;">:</span><span style="color: #000000;">&nbsp;80px;<br>&nbsp;&nbsp;&nbsp;&nbsp;text</span><span style="color: #000000;">-</span><span style="color: #000000;">align</span><span style="color: #000000;">:</span><span style="color: #000000;">left;<br>&nbsp;&nbsp;&nbsp;&nbsp;font</span><span style="color: #000000;">:</span><span style="color: #000000;">normal&nbsp;12px&nbsp;Verdana</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;Arial;<br>&nbsp;&nbsp;&nbsp;&nbsp;background</span><span style="color: #000000;">:</span><span style="color: #008000;">#</span><span style="color: #008000;">FFF</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;}<br>&nbsp;&nbsp;a</span><span style="color: #000000;">:</span><span style="color: #0000ff;">link</span><span style="color: #000000;">,</span><span style="color: #000000;">a</span><span style="color: #000000;">:</span><span style="color: #000000;">visited{<br>&nbsp;&nbsp;&nbsp;&nbsp;text</span><span style="color: #000000;">-</span><span style="color: #000000;">decoration</span><span style="color: #000000;">:</span><span style="color: #000000;">none;<br>&nbsp;&nbsp;&nbsp;&nbsp;color</span><span style="color: #000000;">:</span><span style="color: #008000;">#</span><span style="color: #008000;">333333;</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;}<br>&nbsp;&nbsp;a</span><span style="color: #000000;">:</span><span style="color: #000000;">hover{<br>&nbsp;&nbsp;&nbsp;&nbsp;text</span><span style="color: #000000;">-</span><span style="color: #000000;">decoration</span><span style="color: #000000;">:</span><span style="color: #000000;">none;<br>&nbsp;&nbsp;&nbsp;&nbsp;color</span><span style="color: #000000;">:</span><span style="color: #008000;">#</span><span style="color: #008000;">FF6600</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;}<br>&nbsp;&nbsp;</span><span style="color: #000000;">.</span><span style="color: #000000;">dotline&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;BORDER</span><span style="color: #000000;">-</span><span style="color: #000000;">BOTTOM</span><span style="color: #000000;">-</span><span style="color: #000000;">STYLE</span><span style="color: #000000;">:</span><span style="color: #000000;">&nbsp;dotted;&nbsp;BORDER</span><span style="color: #000000;">-</span><span style="color: #000000;">LEFT</span><span style="color: #000000;">-</span><span style="color: #000000;">STYLE</span><span style="color: #000000;">:</span><span style="color: #000000;">&nbsp;dotted;&nbsp;BORDER</span><span style="color: #000000;">-</span><span style="color: #000000;">RIGHT</span><span style="color: #000000;">-</span><span style="color: #000000;">STYLE</span><span style="color: #000000;">:</span><span style="color: #000000;">&nbsp;dotted;&nbsp;BORDER</span><span style="color: #000000;">-</span><span style="color: #000000;">TOP</span><span style="color: #000000;">-</span><span style="color: #000000;">STYLE</span><span style="color: #000000;">:</span><span style="color: #000000;">&nbsp;dotted<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;/</span><span style="color: #000000;">style</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">script&nbsp;language</span><span style="color: #000000;">=</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">javascript</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;change(name){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;div</span><span style="color: #000000;">=</span><span style="color: #0000ff;">eval</span><span style="color: #000000;">(</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">document.all.</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">+</span><span style="color: #000000;">name);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;div</span><span style="color: #000000;">.</span><span style="color: #000000;">style</span><span style="color: #000000;">.</span><span style="color: #000000;">display</span><span style="color: #000000;">==</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">none</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">?</span><span style="color: #000000;">(div</span><span style="color: #000000;">.</span><span style="color: #000000;">style</span><span style="color: #000000;">.</span><span style="color: #000000;">display</span><span style="color: #000000;">=</span><span style="color: #000000; font-weight: bold;">""</span><span style="color: #000000;">)</span><span style="color: #000000;">:</span><span style="color: #000000;">(div</span><span style="color: #000000;">.</span><span style="color: #000000;">style</span><span style="color: #000000;">.</span><span style="color: #000000;">display</span><span style="color: #000000;">=</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">none</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;</span><span style="color: #000000;">&lt;/</span><span style="color: #000000;">script</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;</span><span style="color: #000000;">&lt;/</span><span style="color: #000000;">head</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">body</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">p&nbsp;align</span><span style="color: #000000;">=</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">center</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">&gt;&lt;</span><span style="color: #000000;">strong</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">您关注的blog列表：</span><span style="color: #000000;">&lt;/</span><span style="color: #000000;">strong</span><span style="color: #000000;">&gt;&lt;/</span><span style="color: #000000;">p</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;%</span><span style="color: #000000;">&nbsp;num</span><span style="color: #000000;">=</span><span style="color: #800000;">1</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">%&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;%</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;blog&nbsp;in&nbsp;blogs&nbsp;</span><span style="color: #000000;">%&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;%</span><span style="color: #000000;">&nbsp;begin&nbsp;</span><span style="color: #000000;">%&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">div</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">a&nbsp;href</span><span style="color: #000000;">=</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">#</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">&nbsp;onclick</span><span style="color: #000000;">=</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">change('blog&lt;%=num%&gt;');</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">&gt;&lt;%=</span><span style="color: #000000;">&nbsp;blog</span><span style="color: #000000;">.</span><span style="color: #000000;">title&nbsp;</span><span style="color: #000000;">%&gt;&lt;/</span><span style="color: #000000;">a</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">div&nbsp;id</span><span style="color: #000000;">=</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">blog&lt;%=num%&gt;</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">&nbsp;style</span><span style="color: #000000;">=</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">display:none</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;%</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">&nbsp;item&nbsp;in&nbsp;blog</span><span style="color: #000000;">.</span><span style="color: #000000;">items&nbsp;</span><span style="color: #000000;">%&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">nbsp;</span><span style="color: #000000;">&amp;</span><span style="color: #000000;">nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">a&nbsp;href</span><span style="color: #000000;">=</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">&lt;%=item.link%&gt;</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">&nbsp;target</span><span style="color: #000000;">=</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">_blank</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">&gt;&lt;%=</span><span style="color: #000000;">&nbsp;item</span><span style="color: #000000;">.</span><span style="color: #000000;">title&nbsp;</span><span style="color: #000000;">%&gt;&lt;/</span><span style="color: #000000;">a</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">br</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;%</span><span style="color: #000000;">&nbsp;end&nbsp;</span><span style="color: #000000;">%&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;/</span><span style="color: #000000;">div</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;/</span><span style="color: #000000;">div</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">hr&nbsp;class</span><span style="color: #000000;">=</span><span style="color: #000000;">dotline&nbsp;color</span><span style="color: #000000;">=</span><span style="color: #008000;">#</span><span style="color: #008000;">000000&nbsp;size=1&gt;</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;%</span><span style="color: #000000;">&nbsp;num</span><span style="color: #000000;">=</span><span style="color: #000000;">num</span><span style="color: #000000;">+</span><span style="color: #800000;">1</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">%&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;%</span><span style="color: #000000;">&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rescue&nbsp;StandardError</span><span style="color: #000000;">=&gt;</span><span style="color: #000000;">e<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts&nbsp;</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">错误信息</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">+</span><span style="color: #000000;">e<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end&nbsp;</span><span style="color: #000000;">%&gt;</span><span style="color: #000000;">&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;%</span><span style="color: #000000;">&nbsp;end&nbsp;</span><span style="color: #000000;">%&gt;</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">&lt;/</span><span style="color: #000000;">body</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #000000;">&lt;/</span><span style="color: #000000;">html</span><span style="color: #000000;">&gt;</span></div>
&nbsp;&nbsp;&nbsp; 遍历blogs数组，然后将blog的title输出到网页，接着就是blog.items文章列表循环输出，将文章列表放在一个div层中以便隐藏，javascript函数change用于隐藏或者显示文章列表。模板文件有了，现在需要的是读取模板文件并render，输出到结果文件：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">&nbsp;&nbsp;blogs</span><span style="color: #000000;">=</span><span style="color: #000000;">rss_read()<br>&nbsp;&nbsp;</span><span style="color: #008000;">#</span><span style="color: #008000;">读取模板文件</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;template</span><span style="color: #000000;">=</span><span style="color: #000000;">IO</span><span style="color: #000000;">.</span><span style="color: #0000ff;">read</span><span style="color: #000000;">(File</span><span style="color: #000000;">.</span><span style="color: #000000;">dirname(</span><span style="color: #0000ff;">__FILE__</span><span style="color: #000000;">)</span><span style="color: #000000;">+</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">/blogs.html</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">)<br>&nbsp;&nbsp;message</span><span style="color: #000000;">=</span><span style="color: #000000;">ERB</span><span style="color: #000000;">.</span><span style="color: #000000;">new(template)<br>&nbsp;&nbsp;</span><span style="color: #008000;">#</span><span style="color: #008000;">输出结果文件</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;File</span><span style="color: #000000;">.</span><span style="color: #0000ff;">open</span><span style="color: #000000;">(</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">today.html</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">,</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">w+</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">){</span><span style="color: #000000;">|</span><span style="color: #000000;">file</span><span style="color: #000000;">|</span><span style="color: #000000;">&nbsp;file</span><span style="color: #000000;">.</span><span style="color: #000000;">puts&nbsp;message</span><span style="color: #000000;">.</span><span style="color: #000000;">result}</span></div>
最后，我们生成的是一个today.html文件，这个网页就是我们就是我们在文章开头处展示的。message.result就是经过render后，将blogs变量传入模板文件后得到结果，我们将它写入today.html。<br>&nbsp;&nbsp;&nbsp; 完整的rss-reader.rb如下：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #0000ff;">require</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">rss/2.0</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">require</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">open-uri</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;"><br></span><span style="color: #0000ff;">require</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">erb</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;"><br></span><span style="color: #008000;">#</span><span style="color: #008000;">&nbsp;author&nbsp;dennis<br>#&nbsp;email&nbsp;killme2008@gmail.com</span><span style="color: #008000;"><br></span><span style="color: #000000;"><br>class&nbsp;Blog<br>&nbsp;&nbsp;attr_accessor</span><span style="color: #000000;">:</span><span style="color: #000000;">title</span><span style="color: #000000;">,:</span><span style="color: #000000;">url</span><span style="color: #000000;">,:</span><span style="color: #000000;">items<br>&nbsp;&nbsp;def&nbsp;initialize(title</span><span style="color: #000000;">,</span><span style="color: #000000;">url</span><span style="color: #000000;">,</span><span style="color: #000000;">items</span><span style="color: #000000;">=</span><span style="color: #000000;">[])<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800080;">@title</span><span style="color: #000000;">=</span><span style="color: #000000;">title<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800080;">@url</span><span style="color: #000000;">=</span><span style="color: #000000;">url<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #800080;">@items</span><span style="color: #000000;">=</span><span style="color: #000000;">items<br>&nbsp;&nbsp;end<br>end<br>def&nbsp;blog_info(url)<br>&nbsp;&nbsp;feed&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;RSS</span><span style="color: #000000;">::</span><span style="color: #000000;">Parser</span><span style="color: #000000;">.</span><span style="color: #000000;">parse(</span><span style="color: #0000ff;">open</span><span style="color: #000000;">(url)</span><span style="color: #000000;">.</span><span style="color: #0000ff;">read</span><span style="color: #000000;">,</span><span style="color: #000000;">&nbsp;false)&nbsp;<br>&nbsp;&nbsp;blog</span><span style="color: #000000;">=</span><span style="color: #000000;">Blog</span><span style="color: #000000;">.</span><span style="color: #000000;">new(feed</span><span style="color: #000000;">.</span><span style="color: #000000;">channel</span><span style="color: #000000;">.</span><span style="color: #000000;">title</span><span style="color: #000000;">,</span><span style="color: #000000;">url</span><span style="color: #000000;">,</span><span style="color: #000000;">feed</span><span style="color: #000000;">.</span><span style="color: #000000;">items)<br>end<br>def&nbsp;rss_read<br>&nbsp;&nbsp;urls</span><span style="color: #000000;">=</span><span style="color: #000000;">[</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">http://www.blogjava.net/canonical/rss</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;">,</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">http://dreamhead.blogbus.com/index.rdf</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;">,</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">http://michael.nona.name/rss</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;">,</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">http://blog.csdn.net/mozilla/Rss.aspx</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;">,</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000; font-weight: bold;">http://blog.csdn.net/g9yuayon/Rss.aspx</span><span style="color: #000000; font-weight: bold;">'</span><span style="color: #000000;">]<br>&nbsp;&nbsp;blogs</span><span style="color: #000000;">=</span><span style="color: #000000;">[]<br>&nbsp;&nbsp;urls</span><span style="color: #000000;">.</span><span style="color: #0000ff;">each</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">do</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">|</span><span style="color: #000000;">blog_url</span><span style="color: #000000;">|</span><span style="color: #000000;"><br>&nbsp;&nbsp;&nbsp;&nbsp;blogs</span><span style="color: #000000;">&lt;&lt;</span><span style="color: #000000;">blog_info(blog_url)<br>&nbsp;&nbsp;end&nbsp;&nbsp;<br>&nbsp;&nbsp;blogs<br>end<br></span><span style="color: #0000ff;">if</span><span style="color: #000000;">&nbsp;$</span><span style="color: #800000;">0</span><span style="color: #000000;">==</span><span style="color: #0000ff;">__FILE__</span><span style="color: #000000;"><br>&nbsp;&nbsp;blogs</span><span style="color: #000000;">=</span><span style="color: #000000;">rss_read()<br>&nbsp;&nbsp;</span><span style="color: #008000;">#</span><span style="color: #008000;">读取模板文件</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;template</span><span style="color: #000000;">=</span><span style="color: #000000;">IO</span><span style="color: #000000;">.</span><span style="color: #0000ff;">read</span><span style="color: #000000;">(File</span><span style="color: #000000;">.</span><span style="color: #000000;">dirname(</span><span style="color: #0000ff;">__FILE__</span><span style="color: #000000;">)</span><span style="color: #000000;">+</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">/blogs.html</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">)<br>&nbsp;&nbsp;message</span><span style="color: #000000;">=</span><span style="color: #000000;">ERB</span><span style="color: #000000;">.</span><span style="color: #000000;">new(template)<br>&nbsp;&nbsp;</span><span style="color: #008000;">#</span><span style="color: #008000;">输出结果文件</span><span style="color: #008000;"><br></span><span style="color: #000000;">&nbsp;&nbsp;File</span><span style="color: #000000;">.</span><span style="color: #0000ff;">open</span><span style="color: #000000;">(</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">today.html</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">,</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">w+</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">){</span><span style="color: #000000;">|</span><span style="color: #000000;">file</span><span style="color: #000000;">|</span><span style="color: #000000;">&nbsp;file</span><span style="color: #000000;">.</span><span style="color: #000000;">puts&nbsp;message</span><span style="color: #000000;">.</span><span style="color: #000000;">result}<br>end<br></span></div>
&nbsp;&nbsp;&nbsp; 使用小窍门：最好将today.html加入FireFox的标签或者IE的收藏夹，windows下建立一个计划任务每天凌晨自动运行rss-reader.rb生成toady.html(linux可以使用cron），那么你每天早上打开浏览器就可以看到牛人们的新鲜文章了^_^<br><img src ="http://www.blogjava.net/killme2008/aggbug/129047.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-07-09 15:14 <a href="http://www.blogjava.net/killme2008/archive/2007/07/09/129047.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ruby字符串String的一个trick</title><link>http://www.blogjava.net/killme2008/archive/2007/07/06/128658.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Fri, 06 Jul 2007 11:39:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/07/06/128658.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/128658.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/07/06/128658.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/128658.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/128658.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 用了这么久ruby，知道String对象可以通过[]操作得到字符或者子字符串，比如：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">&gt;</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">abc</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">[</span><span style="color: #800000;">0</span><span style="color: #000000;">]<br></span><span style="color: #800000;">97</span><span style="color: #000000;"><br></span><span style="color: #000000;">&gt;</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">abc</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">[</span><span style="color: #800000;">0</span><span style="color: #000000;">,</span><span style="color: #800000;">2</span><span style="color: #000000;">]<br></span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">ab</span><span style="color: #000000; font-weight: bold;">"</span></div>
<br>97就是字符a的ASCII码了,却不知道[]操作同样可以接受正则表达式，返回匹配正则的那部分字符串，比如：<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">&gt;</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">has&nbsp;5&nbsp;and&nbsp;3</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">&nbsp;[</span><span style="color: #000000;">/\</span><span style="color: #000000;">d</span><span style="color: #000000;">+/</span><span style="color: #000000;">]<br></span><span style="color: #800000;">5</span><span style="color: #000000;"><br></span><span style="color: #000000;">&gt;</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000; font-weight: bold;">hello&nbsp;there</span><span style="color: #000000; font-weight: bold;">"</span><span style="color: #000000;">[</span><span style="color: #000000;">/</span><span style="color: #000000;">(</span><span style="color: #000000;">..</span><span style="color: #000000;">)e</span><span style="color: #000000;">/</span><span style="color: #000000;">]<br>the</span></div>
<br>ruby的API设计充分体现了马教主所说的<a  href="http://blog.csdn.net/mfowler/archive/2006/10/19/1340358.aspx">人本接口</a>。<br><br> <img src ="http://www.blogjava.net/killme2008/aggbug/128658.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-07-06 19:39 <a href="http://www.blogjava.net/killme2008/archive/2007/07/06/128658.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>迷上了shell编程，推荐好书一本</title><link>http://www.blogjava.net/killme2008/archive/2007/07/05/128347.html</link><dc:creator>dennis</dc:creator><author>dennis</author><pubDate>Thu, 05 Jul 2007 07:06:00 GMT</pubDate><guid>http://www.blogjava.net/killme2008/archive/2007/07/05/128347.html</guid><wfw:comment>http://www.blogjava.net/killme2008/comments/128347.html</wfw:comment><comments>http://www.blogjava.net/killme2008/archive/2007/07/05/128347.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/killme2008/comments/commentRss/128347.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/killme2008/services/trackbacks/128347.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; shell编程，类似dos下的批处理文件，也有很大不同，shell更接近一门编程语言。最近迷上了这玩意，入门很容易，再深入就有点难了，写了几个简单的script处理日常命令，用着蛮爽，大大提高了我继续深入学习linux的积极性，待复习了C语言基础，准备读读《<a href="http://www.china-pub.com/computers/common/info.asp?id=23911" class="blue13" target="_blank">UNIX/LINUX编程实践教程</a>》。前天在emule下了《EveryDay Scripting With Ruby》,这本书在amazon评价很高，昨天一口气读了6章，非常不错。这本书适合ruby初学者，有一定ruby使用经验的也能有不少收获，书中介绍了4个常用的ruby编写的工具脚本，循序渐进、一步一步引你走入ruby的世界，有趣并实用；更可贵的是，这本书从第2个Project开始就以TDD的方式开发，让你充分体验TDD和Ruby结合带来的快感，强烈推荐准备开始学ruby的看看这本书。读这本书主要是想更深入地将ruby使用在我的日常工作中，熟识部分飞快翻过，总共也才250多页，花不了一两天功夫。这本书的源码从网站上下不了，封了来自中国大陆的IP，我将源码传上，有兴趣的看看。<br><br><a href="http://www.blogjava.net/Files/killme2008/bmsft-code.zip">《EveryDay Scripting With Ruby》书中源码</a><br><br>  <img src ="http://www.blogjava.net/killme2008/aggbug/128347.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/killme2008/" target="_blank">dennis</a> 2007-07-05 15:06 <a href="http://www.blogjava.net/killme2008/archive/2007/07/05/128347.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>