﻿<?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>C++博客-swo2006-文章分类-lua</title><link>http://www.cppblog.com/swo2006/category/3195.html</link><description /><language>zh-cn</language><lastBuildDate>Fri, 23 May 2008 01:09:47 GMT</lastBuildDate><pubDate>Fri, 23 May 2008 01:09:47 GMT</pubDate><ttl>60</ttl><item><title>将字符串按“，”分割(lua函数)</title><link>http://www.cppblog.com/swo2006/articles/16000.html</link><dc:creator>swo</dc:creator><author>swo</author><pubDate>Tue, 05 Dec 2006 02:10:00 GMT</pubDate><guid>http://www.cppblog.com/swo2006/articles/16000.html</guid><wfw:comment>http://www.cppblog.com/swo2006/comments/16000.html</wfw:comment><comments>http://www.cppblog.com/swo2006/articles/16000.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/swo2006/comments/commentRss/16000.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/swo2006/services/trackbacks/16000.html</trackback:ping><description><![CDATA[Version 3.69 of MUSHclient adds a new Lua script function: utils.split. This was suggested by Ked.<br /><br />
This is intended to do the reverse of table.concat. That is, it takes a
string and generates a table of entries, delimited by single-character
delimiters (such as comma or newline).<br /><br />
Example:<br /><br /><pre><code><br />test = "the,quick,brown,dog,jumped"  <br /><br />t = utils.split (test, ",")<br /><br />tprint (t)<br /><br />print (table.concat (t, ","))<br /><br /><i>Output:</i><br /><br />1="the"<br />2="quick"<br />3="brown"<br />4="dog"<br />5="jumped"<br /><br />the,quick,brown,dog,jumped<br /></code></pre><br /><br />
You pass utils.split 2 or 3 arguments:<br /><br /><br /><ol><li>The string to be split<br /><br /></li><li>The single-character delimiter<br /><br /></li><li>(optional) the maximum number of splits to do<br /></li></ol><br /><br /><br />
If the 3rd argument is not supplied, or is zero, then the entire string
is split. Otherwise, it will be split the number of times you specify.
eg.<br /><br /><pre><code><br />t = utils.split (test, ",", 2)<br /><br />tprint (t)<br /><br /><i>Output:</i><br /><br />1="the"<br />2="quick"<br />3="brown,dog,jumped"<br /></code></pre><br /><br />
In this case the remaining text is placed in the 3rd table item.<br /><br /><br /><pre><code>static int l_split (lua_State *L) {<br />  const char *s = luaL_checkstring(L, 1);<br />  const char *sep = luaL_checkstring(L, 2);<br />  const int count = (int) luaL_optnumber (L, 3, 0);<br />  char *e;<br />  int i = 1;<br /><br />  if (strlen (sep) != 1)<br />    luaL_error (L, "Separator must be a single character");<br /><br />  if (count &lt; 0)<br />    luaL_error (L, "Count must be positive or zero");<br /><br />  lua_newtable(L);  /* result */<br /><br />  /* repeat for each separator */<br />  while ((e = strchr(s, *sep)) != NULL &amp;&amp; <br />         (count == 0 || i &lt;= count)) <br />    {<br />    lua_pushlstring(L, s, e-s);  /* push substring */<br />    lua_rawseti(L, -2, i++);<br />    s = e + 1;  /* skip separator */<br />    }<br /><br />  /* push last substring */<br />  lua_pushstring(L, s);<br />  lua_rawseti(L, -2, i);<br /><br />  return 1;  /* return the table */<br />}</code></pre><br /><pre><code>function split (s, delim)<br /><br />  assert (type (delim) == "string" and string.len (delim) &gt; 0,<br />          "bad delimiter")<br /><br />  local start = 1<br />  local t = {}  -- results table<br /><br />  -- find each instance of a string followed by the delimiter<br /><br />  while true do<br />    local pos = string.find (s, delim, start, true) -- plain find<br /><br />    if not pos then<br />      break<br />    end<br /><br />    table.insert (t, string.sub (s, start, pos - 1))<br />    start = pos + string.len (delim)<br />  end -- while<br /><br />  -- insert final one (after last delimiter)<br /><br />  table.insert (t, string.sub (s, start))<br /><br />  return t<br /><br />end -- function split</code></pre><img src ="http://www.cppblog.com/swo2006/aggbug/16000.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/swo2006/" target="_blank">swo</a> 2006-12-05 10:10 <a href="http://www.cppblog.com/swo2006/articles/16000.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Lua的多任务机制——协程(coroutine) </title><link>http://www.cppblog.com/swo2006/articles/15781.html</link><dc:creator>swo</dc:creator><author>swo</author><pubDate>Wed, 29 Nov 2006 06:30:00 GMT</pubDate><guid>http://www.cppblog.com/swo2006/articles/15781.html</guid><wfw:comment>http://www.cppblog.com/swo2006/comments/15781.html</wfw:comment><comments>http://www.cppblog.com/swo2006/articles/15781.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/swo2006/comments/commentRss/15781.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/swo2006/services/trackbacks/15781.html</trackback:ping><description><![CDATA[并发是现实世界的本质特征，而聪明的计算机科学家用来模拟并发的技术手段便是多任务机制。大致上有这么两种多任务技术，一种是抢占式多任务
(preemptive multitasking)，它让操作系统来决定何时执行哪个任务。另外一种就是协作式多任务(cooperative
multitasking)，它把决定权交给任务，让它们在自己认为合适的时候自愿放弃执行。这两种多任务方式各有优缺点，前者固有的同步问题使得程序经
常有不可预知的行为，而后者则要求任务具备相当的自律精神。<br />　　　　协程(coroutine)技术是一种程序控制机制，早在上世纪60年代就已
提出，用它可以很方便地实现协作式多任务。在主流的程序语言(如C++、Java、Pascal等)里我们很少能看到协程的身影，但是现在不少动态脚本语
言(Python、Perl)却都提供了协程或与之相似的机制，其中最突出的便是Lua。<br />　　<br />　　　　Lua语言实现的协程是一种非对称
式(asymmetric)协程，或称半对称式(semi-asymmetric)协程，又或干脆就叫半协程(semi-coroutine)。这种协程
机制之所以被称为非对称的，是因为它提供了两种传递程序控制权的操作：一种是(重)调用协程(通过coroutine.resume)；另一种是挂起协程
并将程序控制权返回给协程的调用者(通过coroutine.yield)。一个非对称协程可以看做是从属于它的调用者的，二者的关系非常类似于例程
(routine)与其调用者之间的关系。既然有非对称式协程，当然也就有对称式(symmetric)协程了，它的特点是只有一种传递程序控制权的操
作，即将控制权直接传递给指定的协程。曾经有这么一种说法，对称式和非对称式协程机制的能力并不等价，但事实上很容易根据前者来实现后者。接下来我们就用
代码来证明这个事实。<br />　　<br />　　--对称式协程库coro.lua<br />　　<br />　　coro = {}<br />　　--coro.main用来标识程序的主函数<br />　　coro.main = function() end<br />　　-- coro.current变量用来标识拥有控制权的协程，<br />　　-- 也即正在运行的当前协程<br />　　coro.current = coro.main<br />　　<br />　　-- 创建一个新的协程<br />　　function coro.create(f)<br />　　　 return coroutine.wrap(function(val)<br />　　　　　　　　　　　　　　　　return nil,f(val)<br />　　　　　　　　　　　　　　 end)<br />　　end<br />　　<br />　　-- 把控制权及指定的数据val传给协程k<br />　　function coro.transfer(k,val)<br />　　　 if coro.current ~= coro.main then<br />　　　　　return coroutine.yield(k,val)<br />　　　 else<br />　　　　　-- 控制权分派循环<br />　　　　　while k do<br />　　　　　　 coro.current = k<br />　　　　　　 if k == coro.main then<br />　　　　　　　　return val<br />　　　　　　 end<br />　　　　　　 k,val = k(val)<br />　　　　　end<br />　　　　　error("coroutine ended without transfering control...")<br />　　　 end<br />　　end<br />　　<br />　　如果暂时还弄不懂上面的程序，没关系，看看如何使用这个库后再回头分析。下面是使用示例：<br />　　<br />　　require("coro.lua")<br />　　<br />　　function foo1(n)<br />　　　 print("1: foo1 received value "..n)<br />　　　 n = coro.transfer(foo2,n + 10)<br />　　　 print("2: foo1 received value "..n)<br />　　　 n = coro.transfer(coro.main,n + 10)<br />　　　 print("3: foo1 received value "..n)<br />　　　 coro.transfer(coro.main,n + 10)<br />　　end<br />　　<br />　　function foo2(n)<br />　　　 print("1: foo2 received value "..n)<br />　　　 n = coro.transfer(coro.main,n + 10)<br />　　　 print("2: foo2 received value "..n)<br />　　　 coro.transfer(foo1,n + 10)<br />　　end<br />　　<br />　　function main()<br />　　　 foo1 = coro.create(foo1)<br />　　　 foo2 = coro.create(foo2)<br />　　　 local n = coro.transfer(foo1,0)<br />　　　 print("1: main received value "..n)<br />　　　 n = coro.transfer(foo2,n + 10)<br />　　　 print("2: main received value "..n)<br />　　　 n = coro.transfer(foo1,n + 10)<br />　　　 print("3: main received value "..n)<br />　　end<br />　　<br />　　--把main设为主函数(协程)<br />　　coro.main = main<br />　　--将coro.main设为当前协程<br />　　coro.current = coro.main<br />　　--开始执行主函数(协程)<br />　　coro.main()<br />　　<br />　　<br />　
　上面的示例定义了一个名为main的主函数，整个程序由它而始，也因它而终。为什么需要一个这样的主函数呢？上面说了，程序控制权可以在对称式协程之间
自由地直接传递，它们之间无所谓谁从属于谁的问题，都处于同一个层级，但是应用程序必须有一个开始点，所以我们定义一个主函数，让它点燃程序运行的导火
线。虽说各个协程都是平等的，但做为程序运行原动力的主函数仍然享有特殊的地位(这个世上哪有绝对的平等！)，为此我们的库专门用了一个
coro.main变量来保存主函数，并且在它执行之前要将它设为当前协程(虽然上面的main实际只是一个普通函数而非一个真正的协程，但这并无太大的
关系，以后主函数也被称为主协程)。示例运行的结果是：<br />　　<br />　　1: foo1 received value 0<br />　　1: foo2 received value 10<br />　　1: main received value 20<br />　　2: foo2 received value 30<br />　　2: foo1 received value 40<br />　　2: main received value 50<br />　　3: foo1 received value 60<br />　　3: main received value 70<br />　　<br />　　协程的执行序列是：main-&gt;foo1-&gt;foo2-&gt;main-&gt;foo2-&gt;foo1-&gt;main-&gt;foo1-&gt;main。<br />　　<br />　
　　　coro.transfer(k,val)函数中k是将要接收程序控制权的协程，而val是传递给k的数据。如果当前协程不是主协程，
tansfer(k,val)就简单地利用coroutine.yield(k,val)将当前协程挂起并传回两项数据，即程序控制权的下一站和传递给它
的数据；否则进入一个控制权分派(dispatch)循环，该循环(重)启动(resume)k协程，等待它执行到挂起(suspend)，并根据此时协
程传回的数据来决定下一个要(重)启动的协程。从应用示例来看，协程与协程之间似乎是用transfer直接传递控制权的，但实际上这个传递还是通过了主
协程。每一个在主协程里被调用(比较coro.current和coro.main是否相同即可判断出)的transfer都相当于一个协程管理器，它不
断地(重)启动一个协程，将控制权交出去，然后等那个协程挂起时又将控制权收回，然后再(重)启动下一个协程...，这个动作不会停止，除非&lt;
1&gt;将(重)启动的协程是主协程；&lt;2&gt;某个协程没有提供控制权的下一个目的地。很显然，每一轮分派循环开始时都由主协程把握控制权，
在循环过程中如果控制权的下一站又是主协程的话就意味着这个当初把控制权交出去的主协程transfer操作应该结束了，所以函数直接返回val从而结束
这轮循环。对于情况&lt;2&gt;，因为coro.create(f)创建的协程的体函数(body
function)实际是function(val) return nil,f(val)
end，所以当函数f的最后一条指令不是transfer时，这个协程终将执行完毕并把nil和函数f的返回值一起返回。如果k是这样的协程，
transfer执行完k,val =
k(val)语句后k值就成了nil，这被视为一个错误，因为程序此时没法确定下一个应该(重)启动的协程到底是谁。所以在对称式模型下，每一个协程(当
然主协程出外)最后都必须显式地将控制权传递给其它的协程。根据以上分析，应用示例的控制权的分派应为：<br />　　<br />　　第一轮分派: main-&gt;foo1-&gt;main-&gt;foo2-&gt;main-&gt;main(结束)<br />　　第二轮分派: main-&gt;foo2-&gt;main-&gt;foo1-&gt;main-&gt;main(结束)<br />　　第三轮分派: main-&gt;foo1-&gt;main-&gt;main(结束)<br />　　<br />　
　　　由于可以直接指定控制权传递的目标，对称式协程机制拥有极大的自由，但得到这种自由的代价却是牺牲程序结构。如果程序稍微复杂一点，那么即使是非常
有经验的程序员也很难对程序流程有全面而清晰的把握。这非常类似goto语句，它能让程序跳转到任何想去的地方，但人们却很难理解充斥着goto的程序。
非对称式协程具有良好的层次化结构关系，(重)启动这些协程与调用一个函数非常类似：被(重)启动的协程得到控制权开始执行，然后挂起(或结束)并将控制
权返回给协程调用者，这与计算机先哲们倡导的结构化编程风格完全一致。<br />　　<br />　　　　综上所述，Lua提供的非对称式协程不但具有与对称式协程一样强大的能力，而且还能避免程序员滥用机制写出结构混乱的程序。<img src ="http://www.cppblog.com/swo2006/aggbug/15781.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/swo2006/" target="_blank">swo</a> 2006-11-29 14:30 <a href="http://www.cppblog.com/swo2006/articles/15781.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>fuction(lua)</title><link>http://www.cppblog.com/swo2006/articles/15732.html</link><dc:creator>swo</dc:creator><author>swo</author><pubDate>Tue, 28 Nov 2006 06:43:00 GMT</pubDate><guid>http://www.cppblog.com/swo2006/articles/15732.html</guid><wfw:comment>http://www.cppblog.com/swo2006/comments/15732.html</wfw:comment><comments>http://www.cppblog.com/swo2006/articles/15732.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/swo2006/comments/commentRss/15732.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/swo2006/services/trackbacks/15732.html</trackback:ping><description><![CDATA[
		<font face="Courier New" size="4">Lua中的函数是一阶类型值(first-class value)，定义函数就象创建普通类型值一样(只不过函数类型</font>
		<font face="Courier New" size="4">值的数据主要是一条条指令而已)，所以在函数体中仍然可以定义函数。假设函数f2定义在函数f1中，那么就称</font>
		<font face="Courier New" size="4">f2为f1的内嵌(inner)函数，f1为f2的外包(enclosing)函数，外包和内嵌都具有传递性，即f2的内嵌必然是</font>
		<font face="Courier New" size="4">f1的内嵌，而f1的外包也一定是f2的外包。内嵌函数可以访问外包函数已经创建的所有局部变量，这种特性便是</font>
		<font face="Courier New" size="4">所谓的词法定界(lexical scoping)，而这些局部变量则称为该内嵌函数的外部局部变量(external local </font>
		<font face="Courier New" size="4">variable)或者upvalue(这个词多少会让人产生误解，因为upvalue实际指的是变量而不是值)。试看如下代</font>
		<font face="Courier New" size="4">码：</font>
		<p>
				<font color="#a52a2a" face="Courier New" size="4">function f1(n)<br />   <font color="#006400">-- 函数参数也是局部变量</font></font>
		</p>
		<p>
				<font color="#a52a2a" face="Courier New" size="4">   local function f2()<br />      print(n) <font color="#006400">-- 引用外包函数的局部变量</font><br />   end<br />   return f2<br />end</font>
		</p>
		<p>
				<font color="#a52a2a" face="Courier New" size="4">g1 = f1(1979)<br />g1() <font color="#006400">-- 打印出1979</font><br />g2 = f1(500)<br />g2() <font color="#006400">-- 打印出500</font></font>
		</p>
		<p>
				<font face="Courier New" size="4">当执行完g1 = f1(1979)后，局部变量n的生命本该结束，但因为它已经成了内嵌函数f2(它又被赋给了变量</font>
				<font face="Courier New" size="4">g1)的upvalue，所以它仍然能以某种形式继续“存活”下来，从而令g1()打印出正确的值。</font>
		</p>
		<p>
				<font face="Courier New" size="4">    可为什么g2与g1的函数体一样(都是f1的内嵌函数f2的函数体)，但打印值不同？这就涉及到一个相当重要</font>
				<font face="Courier New" size="4">的概念——闭包(closure)。事实上，Lua编译一个函数时，会为它生成一个原型(prototype)，其中包含了</font>
				<font face="Courier New" size="4">函数体对应的虚拟机指令、函数用到的常量值(数，文本字符串等等)和一些调试信息。在运行时，每当Lua执行</font>
				<font face="Courier New" size="4">一个形如function...end 这样的表达式时，它就会创建一个新的数据对象，其中包含了相应函数原型的引用</font>
				<font face="Courier New" size="4">、环境(environment，用来查找全局变量的表)的引用以及一个由所有upvalue引用组成的数组，而这个数据</font>
				<font face="Courier New" size="4">对象就称为闭包。由此可见，函数是编译期概念，是静态的，而闭包是运行期概念，是动态的。g1和g2的值严格</font>
				<font face="Courier New" size="4">来说不是函数而是闭包，并且是两个不相同的闭包，而每个闭包可以保有自己的upvalue值，所以g1和g2打印出</font>
				<font face="Courier New" size="4">的结果当然就不一样了。虽然闭包和函数是本质不同的概念，但为了方便，且在不引起混淆的情况下，我们对它</font>
				<font face="Courier New" size="4">们不做区分。</font>
		</p>
		<p>
				<font face="Courier New" size="4">    使用upvalue很方便，但它们的语义也很微妙，需要引起注意。比如将f1函数改成：</font>
		</p>
		<p>
				<font color="#a52a2a" face="Courier New" size="4">function f1(n)<br />   local function f2()<br />      print(n)<br />   end<br />   n = n + 10<br />   return f2<br />end</font>
		</p>
		<p>
				<font color="#a52a2a" face="Courier New" size="4">g1 = f1(1979)<br />g1() <font color="#006400">-- 打印出1989</font></font>
		</p>
		<p>
				<font face="Courier New" size="4">内嵌函数定义在n = n + 10这条语句之前，可为什么g1()打印出的却是1989？upvalue实际是局部变量，而</font>
				<font face="Courier New" size="4">局部变量是保存在函数堆栈框架上(stack frame)的，所以只要upvalue还没有离开自己的作用域，它就一直</font>
				<font face="Courier New" size="4">生存在函数堆栈上。这种情况下，闭包将通过指向堆栈上的upvalue的引用来访问它们，一旦upvalue即将离开</font>
				<font face="Courier New" size="4">自己的作用域(这也意味着它马上要从堆栈中消失)，闭包就会为它分配空间并保存当前的值，以后便可通过指向</font>
				<font face="Courier New" size="4">新分配空间的引用来访问该upvalue。当执行到f1(1979)的n = n + 10时，闭包已经创建了，但是n并没有离</font>
				<font face="Courier New" size="4">开作用域，所以闭包仍然引用堆栈上的n，当return f2完成时，n即将结束生命，此时闭包便将n(已经是1989</font>
				<font face="Courier New" size="4">了)复制到自己管理的空间中以便将来访问。弄清楚了内部的秘密后，运行结果就不难解释了。</font>
		</p>
		<p>
				<font face="Courier New" size="4">    upvalue还可以为闭包之间提供一种数据共享的机制。试看下例：</font>
		</p>
		<p>
				<font color="#a52a2a" face="Courier New" size="4">function Create(n)<br />   local function foo1()<br />      print(n)<br />   end</font>
		</p>
		<p>
				<font color="#a52a2a" face="Courier New" size="4">   local function foo2()<br />      n = n + 10<br />   end</font>
		</p>
		<p>
				<font color="#a52a2a" face="Courier New" size="4">   return foo1,foo2<br />end</font>
		</p>
		<p>
				<font color="#a52a2a" face="Courier New" size="4">f1,f2 = Create(1979)<br />f1() <font color="#006400">-- 打印1979</font><br />f2()<br />f1() <font color="#006400">-- 打印1989</font><br />f2()<br />f1() <font color="#006400">-- 打印1999</font></font>
		</p>
		<p>
				<font face="Courier New" size="4">f1,f2这两个闭包的原型分别是Create中的内嵌函数foo1和foo2，而foo1和foo2引用的upvalue是同一个，</font>
				<font face="Courier New" size="4">即Create的局部变量n。前面已说过，执行完Create调用后，闭包会把堆栈上n的值复制出来，那么是否f1和f2</font>
				<font face="Courier New" size="4">就分别拥有一个n的拷贝呢？其实不然，当Lua发现两个闭包的upvalue指向的是当前堆栈上的相同变量时，会聪</font>
				<font face="Courier New" size="4">明地只生成一个拷贝，然后让这两个闭包共享该拷贝，这样任一个闭包对该upvalue进行修改都会被另一个探知</font>
				<font face="Courier New" size="4">。上述例子很清楚地说明了这点：每次调用f2都将upvalue的值增加了10，随后f1将更新后的值打印出来。</font>
				<font face="Courier New" size="4">upvalue的这种语义很有价值，它使得闭包之间可以不依赖全局变量进行通讯，从而使代码的可靠性大大提高。</font>
		</p>
		<p>
				<font face="Courier New" size="4">    闭包在创建之时其upvalue就已经不在堆栈上的情况也有可能发生，这是因为内嵌函数可以引用更外层外包函数</font>
				<font face="Courier New" size="4">的局部变量：</font>
		</p>
		<p>
				<font color="#a52a2a" face="Courier New" size="4">function Test(n)<br />   local function foo()<br />      local function inner1()<br />         print(n)<br />      end<br />      local function inner2()<br />         n = n + 10<br />      end<br />      return inner1,inner2<br />   end<br />   return foo<br />end</font>
		</p>
		<p>
				<font color="#a52a2a" face="Courier New" size="4">t = Test(1979)<br />f1,f2 = t()<br />f1()        <font color="#006400">-- 打印1979</font><br />f2()<br />f1()        <font color="#006400">-- 打印1989</font><br />g1,g2 = t()<br />g1()        <font color="#006400">-- 打印1989</font><br />g2()<br />g1()        <font color="#006400">-- 打印1999</font><br />f1()        <font color="#006400">-- 打印1999</font></font>
		</p>
		<p>
				<font face="Courier New" size="4">执行完t = Test(1979)后，Test的局部变量n就“死”了，所以当f1,f2这两个闭包被创建时堆栈上根本找不到</font>
				<font face="Courier New" size="4">n的踪影，这叫它们如何取得n的值呢？呵呵，不要忘了Test函数的n不仅仅是inner1和inner2的upvalue，同</font>
				<font face="Courier New" size="4">时它也是foo的upvalue。t = Test(1979)之后，t这个闭包一定已经把n妥善保存好了，之后f1、f2如果在</font>
				<font face="Courier New" size="4">当前堆栈上找不到n就会自动到它们的外包闭包(姑且这么叫)的upvalue引用数组中去找，并把找到的引用值拷</font>
				<font face="Courier New" size="4">贝到自己的upvalue引用数组中。仔细观察上述代码，可以判定g1和g2与f1和f2共享同一个upvalue。这是为</font>
				<font face="Courier New" size="4">什么呢？其实，g1和g2与f1和f2都是同一个闭包(t)创建的，所以它们引用的upvalue(n)实际也是同一个变量</font>
				<font face="Courier New" size="4">，而刚才描述的搜索机制则保证了最后它们的upvalue引用都会指向同一个地方。</font>
		</p>
		<p>
				<font face="Courier New" size="4">    Lua将函数做为基本类型值并支持词法定界的特性使得语言具有强大的抽象能力。而透彻认识函数、闭包和</font>
				<font face="Courier New" size="4">upvalue将帮助程序员善用这种能力。</font>
		</p>
<img src ="http://www.cppblog.com/swo2006/aggbug/15732.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/swo2006/" target="_blank">swo</a> 2006-11-28 14:43 <a href="http://www.cppblog.com/swo2006/articles/15732.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>