在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
词法域:若将一个函数写在另一个函数之内,那么这个位于内部的函数便可以访问外部函数中的局部变量,这项特征称之为“词法域”。 names = {"Peter", "Paul", "Mary"} grades = {Mary = 10, Paul = 7, Peter = 8} table.sort(names, function (n1, n2) return grades[n1] > grades[n2] -- 比较年级 end) 现在假设单独创建一个函数来做这项工作: function sortbygrade (names, grades) table.sort(names, function (n1, n2) return grades[n1] > grades[n2] -- 比较年级 end) end 上例中有一点很有趣,传递给sort的匿名函数可以访问参数grades,而grades是外部函数sortbygrade的局部变量。在这个匿名函数内部,grades既不是全局变量也不是局部变量,将其称为一个“非局部的变量(non-local variable)”。 function newCounter() local i = 0 return function () -- 匿名函数 i = i + 1 return i end end c1 = newCounter() print(c1()) --> 1 print(c1()) --> 2 在这段代码中,匿名函数访问了一个“非局部的变量”i,改变两用于保持一个计数器。出刊上去,由于创建变量i的函数(newCounter)已经返回,所以之后每次调用匿名函数时,i都应该是已超出作用范围的。但其实不然,Lua会以closure的概念来正确地处理这种情况。简单地说,一个closure就是一个函数加上该函数所需访问的所有“非局部的变量”。如果再次调用newCounter,那么它会创建一个新的局部变量i,从而也将得到一个新的closure: c2 = newCOunter() print(c2()) --> 1 print(c1()) --> 3 print(c2()) --> 2 因此c1和c2是同一个函数所创建的两个不同的closure,它们各自拥有局部变量i的独立实例。 function digitButton (digit) return Button{ label = tostring(digit), action = function () add_to_display(digit) end } end closure在另一种情况中也非常有用。例如在Lua中函数是存储在普通变量中的,因此可以轻易地重新定义某些函数,甚至是重新定义那些预定以的函数。这正是Lua相当灵活的原因之一。通常当重新定义一个函数的时候,需要在新的视线中调用原来的那个函数。举例来说,假设要重新定义函数sin,使其参数能使用角度来替换原先的弧度。那么这个心寒数就必须得转换他的实参,并调用原来的sin函数完成真正的计算。这段代码可能是这样的: oldSin = math.sin math.sin = function (x) return oldSin(x*math.pi/180) end 还有一种更彻底的做法是这样的: do local oldSin = math.sin local k = math.pi/180 math.sin = function (x) return oldSin(x*k) end end 将老版本的sin保存到了一个私有变量中,现在只有通过新版本的sin才能访问它了。 do local oldOpen = io.open local access_OK = function (filename, mode) <检查访问权限> end io.open = function (filename, mode) if access_OK(filename, mode) then return oldOpen(filename, mode) else return nil, "access denied" end end end 这个示例的精彩之处在于,经过重新定义后,一个程序就只能呢该通过新的受限版本来调用原来哪个未受限的open函数了。示例将原来不安全的版本保存到closure的一个私有变量中,从而使得外部再也无法直接访问到原来的版本了。通过这种技术,可以在Lua的语言层面上就构建除一个安全地运行环境,且不是简易性了灵活性。相对于提供一套大而全的解决方案,Lua提供的则是一套“元机制(meta-mechanism)”,因此可以根据特定的安全需要来创建一个安全的运行环境。 |
请发表评论