﻿<?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-庄周梦蝶，孰蝶是我，我是孰蝶？一梦至今，蝶我已难分-随笔分类-my open-source</title><link>http://www.blogjava.net/killme2008/category/20771.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 17 Apr 2008 15:15:55 GMT</lastBuildDate><pubDate>Thu, 17 Apr 2008 15:15:55 GMT</pubDate><ttl>60</ttl><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>0</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>发布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<