Lua学习笔记(一)

1: 字符串转化为数字类型, tonumber
数字类型转化为字符串, tostring
.. 为字符串连接运算符
print (0 .. 1)   --> 01
print (10 .. "" == "10")  等价于 print (tostirng(10) == "10")

2:
C 语言中的三元运算符
a?b:c
在 Lua 中可以这样实现:
(a and b) or c

3: 除了^和..外所有的二元运算符都是左连接的。
x^y^z <--> x^(y^z)

4: 遇到赋值语句,lua会首先计算右边所有的值,然后赋值给左边,也就是隐式创建了临时变量,所以可以进行变量的交换

x, y = y, x --  swap  x,y的值
a[i], a[j] = a[j], a[i] -- swap a[i],a[j]的值

5: 当变量个数和值的个数不一致时,Lua 会一直以变量个数为基础采取以下策略:

 a. 变量个数>值的个数 按变量个数补足nil
b. 变量个数<值的个数 多余的值会被忽略

例如:
a, b, c = 0, 1
print(a,b,c) --> 0  1 nil
a, b = a+1, b+1, b+2
print(a,b) --> 1   2
a, b, c = 0 --> 0 nil nil
print(a,b,c)

6: 第一,当作为表达式调用函数时,有以下几种情况:
1. 当调用作为表达式最后一个参数或者仅有一个参数时,根据变量个数函数尽可能
多地返回多个值,不足补 nil,超出舍去。
2. 其他情况下,函数调用仅返回第一个值(如果没有返回值为 nil)

假设有如下三个函数:
  function foo0 () end -- returns no results
function foo1 () return 'a' end -- returns 1 result
function foo2 () return 'a','b' end -- returns 2 results

x,y = foo2(), 20 -- x='a', y=20
x,y = foo0(), 20, 30 -- x='nil', y=20, 30 is discarded

第二,函数调用作为函数参数被调用时,和多值赋值是相同。

print(foo0()) -->
print(foo1()) --> a
print(foo2()) --> a  b
print(foo2(),1) --> a 1
print(foo2() .. "x") --> ax

第三,函数调用在表构造函数中初始化时,和多值赋值时相同。

a = {foo0()} -- a = {} (an empty table)
a = {foo1()} -- a = {'a'}
a = {foo2()} -- a = {'a', 'b'}
a = {foo0(), foo2(), 4} -- a[1] = nil, a[2] = 'a', a[3] = 4

另外,return f()这种类型的返回 f()返回的所有值

function foo (i)
   if i == 0 then return foo0()
   elseif i == 1 then return foo1()
   elseif i == 2 then return foo2()
   end
end

print(foo(1)) --> a
print(foo(2)) --> a b
print(foo(0)) -- (no results)
print(foo(3)) -- (no results)

可以使用圆括号强制使调用返回一个值。一个 return 语句如果使用圆括号将返回值括起来也将导致返回一个值。

print((foo0())) --> nil
print((foo1())) --> a
print((foo2())) --> a

7: 利用可变参数声明一个 select 函数:
function select (n, ...)
   return arg[n]
end
print(string.find("hello hello", " hel")) --> 6 9
print(select(1, string.find("hello hello", " hel"))) --> 6
print(select(2, string.find("hello hello", " hel"))) --> 9

8: 闭包。

function newCounter()
    local i = 0
    return  function() i=i+1
            return i
            end
end

闭包内的匿名函数使用 upvalue i 保存他的计数,当我们调用匿名函数的时候 i 已经超出了作 用范围,因为创建 i 的函数 newCounter 已经返回了。然而 Lua 用闭包的思想正确处理了这种情况。

c1 = newCounter()
print(c1) --> function: 0x8af6750
print(c1()) --> 1
print(c1()) --> 2

print(newCounter()) --> function: 0x8af6c60

print(newCounter()) --> function: 0x8af6c60

print(newCounter()()) --> 1

print(newCounter()()) --> 1

由此可见,闭包函数返回的是一个函数,当再次调用这个返回的函数的时候,他访问的外部的变量依然存在在某个作用域

简单的说闭包是一个函数加上它可以正确访问的 upvalues。如果我们再次调 用 newCounter,将创建一个新的局部变量 i,因此我们得到了一个作用在新的变量 i 上的 新闭包。

c2 = newCounter()
print(c2()) --> 1
print(c1()) --> 3
print(c2()) --> 2

9: 非全局函数
Lua 中函数可以作为全局变量也可以作为局部变量,我们已经看到一些例子:函数 作为table的域(大部分Lua标准库使用这种机制来实现的比如io.read、math.sin)。这种 情况下,必须注意函数和表语法:
1. 表和函数放在一起
Lib = {}
Lib.foo = function (x,y) return x + y end
Lib.goo = function (x,y) return x - y end

2. 使用表构造函数
Lib = {
   foo = function (x,y) return x + y end,
   goo = function (x,y) return x - y end
   }

   3. Lua 提供另一种语法方式
   Lib = {}
function Lib.foo (x,y)
   return x + y
end
function Lib.goo (x,y)
   return x - y
end

当我们将函数保存在一个局部变量内时,我们得到一个局部函数,也就是说局部函 数像局部变量一样在一定范围内有效。
下面是声明局部函数的两种方式:
1. 方式一

local f = function (...)
   ...
end
local g = function (...)
   ...
f() --externallocal`f'isvisiblehere
...
end

2. 方式二
有一点需要注意的是在声明递归局部函数的方式:
local function f (...)
   ...
end

local fact = function (n)
   if n == 0 then
return 1 else
       return n*fact(n-1) -- buggy
end end

上面这种方式导致 Lua 编译时遇到 fact(n-1)并不知道他是局部函数 fact,Lua 会去查找是否有这样的全局函数 fact。为了解决这个问题我们必须在定义函数以前先声明:

local fact
fact = function (n)
   if n == 0 then
return 1 else
    return n*fact(n-1)
   end
end

这样在 fact 内部 fact(n-1)调用是一个局部函数调用,运行时 fact 就可以获取正确的 值了。

但是 Lua 扩展了他的语法使得可以在直接递归函数定义时使用两种方式都可以。 在定义非直接递归局部函数时要先声明然后定义才可以:

local f, g -- `forward' declarations
function g ()
... f() ...
end
function f ()
... g() ...
end

10: 一个 list 写一个简单的迭代器

function list_iter (t)
   local i = 0
   local n = table.getn(t)      --返回list的size
   return function ()
        i=i+1
        if i <= n then return t[i] end
   end
end

t = {10, 20, 30,5,6,7}
iter = list_iter(t)     -- creates the iterator
while true do
    local element=iter()     --calls the iterator
    if element == nil then
        break
    end
   
    print(element)
end

我们设计的这个迭代器也很容易用于范性 for 语句

t = {10, 20, 30}
for element in list_iter(t) do
   print(element)
end

猜你喜欢

转载自7090.iteye.com/blog/1848140