Lua基础语法

注释

  • 单行注释
    两个减号,--

  • 多行注释
    --[[ 内容 --]]

数据类型

  • Lua是动态类型语言,变量不需要类型定义,只需为变量赋值

数据类型 | 描述
—|—
nil | 只有值”nil”属于该类,表示一个无效值(在条件表达式里相当于false)
boolean | false 和 true
number | 双精度类型的实浮点数
string | 由一对双引号" "或单引号' '表示
function | 由C或Lua编写的函数
userdata | 表示任意存储在变量中的C数据结构
thread | 表示执行的独立线路
table | Lua 中的表(table)其实是一个”关联数组”(associative arrays),数组的索引可以是数字或者是字符串。在 Lua 里,table 的创建是通过”构造表达式”来完成,最简单构造表达式是{},用来创建一个空表。

nil

  • nil类型表示一种没有任何有效值,它只有一个值”nil”
  • 对于全局变量和table,nil的另外一个作用为删除,给全局变量或table表里的变量赋值nil,等于把它们删掉

boolean

  • Lua把false和nil看作“假”,其余为“真”

number

  • Lua默认只有一种number类型,即double(双精度)类型,默认类型可以修改luaconf.h里的定义。以下几种写法都是number类型

    >print(type(2))   >print(type(2.2))   >print(type(0.2))   >print(type(2e+1))   >print(type(0.2e-1))   >print(type(7.8263692594256e-06))  
    

    number
    number
    number
    number
    number
    number


string


  • 在对一个数字字符串上进行算术操作时,Lua会将数字字符串转成一个数字

    > print("2" + 6)   8.0   > print("2" + "6")   8.0   > print("2 + 6")   2 + 6   > print("-2e2" * "6")   -1200.0   > print("error" + 1)   stdin:1: attempt to perform arithmetic on a string value   stack traceback:  
    stdin:1: in main chunk  
    [C]: in ?   >  
    

  • 字符串连接需要用..,需加上空格

    >print('a' .. 'b')   ab  
    

    print(157 .. 333)
    157333


  • 使用#计算字符串的长度,放在字符串前面

    >len='www.w3cshool.cc'   >print(#len)   16   >print(#'www.w3cschool.cc')   16  
    

table

local table1={}  
  
--初始表  
local table2={'apple','pear','orange','grape'}  

  • Lua中的table是一个”关联数组”,数组的索引可以数字或字符串
    【注】 Lua中table 默认初始索引从1开始

    a={}   a['key']='value'   key=10   a[key]=22   a[key]=a[key]+11  
    

    for k,v in ipairs(a) do
    print(k .. ‘:’ .. v)
    end

    结果
    key:value
    10:33


function

  • 在Lua中,function被看作是”第一类值(First-Class Value)”,函数可以存在变量里

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

    print(factorial1(5))

    factorial2=factorial1
    print(fatorial2(5))

    结果
    120
    120


userdata

userdata 是一种用户自定义数据,用于表示一种由应用程序或 C/C++ 语言库所创建的类型,可以将任意 C/C++ 的任意数据类型的数据(通常是 struct 和 指针)存储到 Lua 变量中调用。

变量

  • 变量在使用前,必须在代码中进行声明,即创建该变量。
  • Lua 变量有三种类型:全局变量、局部变量、表中的域
  • 变量的默认值均为 nil。

标识符

  • 一般用下划线加大写字母的标识符,为Lua的保留字。如:_VERSION 为保留用于Lua内部全局变量
  • 区分大小写

全局变量

  • 默认是全局变量
  • 全局变量无需声明,给一个变量赋值后即创建了这个全局变量,访问一个没有初始化的全局变量也不会出错,得到的结果为:nil

    print(b)   >nil   b=10   print(b)   >10  
    

  • 删除一个全局变量,将变量赋值为nil即可

    b=nil   print(b)   >nil  
    

局部变量

使用local声明
应该尽可能的使用局部变量,有两个好处:

  1. 避免命名冲突。
  2. 访问局部变量的速度比全局变量更快。

赋值语句

  • Lua可以对多个变量同时赋值,变量列表和值列表的各个元素用逗号分开,赋值语句右边的值会依次赋给左边的变量。

    a, b = 10, 2*x       <-->       a=10; b=2*x  
    

  • 遇到赋值语句Lua会先计算右边所有的值然后再执行赋值操作,所以我们可以这样进行交换变量的值:

    x, y = y, x                     -- swap 'x' for 'y'   a[i], a[j] = a[j], a[i]         -- swap 'a[i]' for 'a[j]'  
    

  • 当变量个数和值的个数不一致时,Lua会一直以变量个数为基础采取以下策略:
  1. 变量个数 > 值的个数 按变量个数补足nil
  2. 变量个数 < 值的个数 多余的值会被忽略
>a, b, c = 0, 1  
>print(a,b,c)               
  
0   1   nil  
   
>a, b = a+1, b+1, b+2     -- value of b+2 is ignored  
>print(a,b)                 
>1   2  
   
>a, b, c = 0  
>print(a,b,c)               
  
0   nil   nil  

  • 多值赋值经常用来交换变量,或将函数调用返回给变量:

    a,b=fun()  
    

f()返回两个值,第一个赋给a,第二个赋给b。

循环

while

while(condition)  
do  
	statements  
end  

for

Lua中for语句有两大类:

  • 数值for循环
  • 泛型for循环

数值for循环

for var=exp1,exp2,exp3 do  
	statements  
end  

  • var从exp1变化到exp2,每次变化以exp3为步长递增var,并执行一次”执行体”。exp3是可选的,如果不指定,默认为1
  • for的三个表达式在循环开始前一次性求值,以后不再进行求值。

泛型for循环

用过一个迭代器遍历所有值

    --打印数组a 的所有值  
for i,v in ipairs(a)  
	do print(v)  
end  

i是数组索引值,v是对应索引的数组元素值。ipairs是Lua提供的一个迭代器函数,用来迭代数组。

days={"Suanday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"}  
  
for i,v in ipairs(days) do  
	print(v)  
end  
  
  
结果  
Suanday  
Monday  
Tuesday  
Wednesday  
Thursday  
Friday  
Saturday  

repeat…until

Lua 编程语言中 repeat…until 循环语句不同于 for 和 while循环,for 和 while 循环的条件语句在当前循环执行开始时判断,而 repeat…until 循环的条件语句在当前循环结束后判断。

repeat  
	statements  
until(contidion)  

我们注意到循环条件判断语句(condition)在循环体末尾部分,所以在条件进行判断前循环体都会执行一次。

函数

函数作为参数

Lua 中我们可以将函数作为参数传递给函数

myprint = function(param)  
   print("这是打印函数 -   ##",param,"##")  
end  
  
function add(num1,num2,functionPrint)  
   result = num1 + num2  
   -- 调用传递的函数参数  
   functionPrint(result)  
end  
myprint(10)  
-- myprint 函数作为参数传递  
add(2,5,myprint)  
  
结果  
这是打印函数 -   ##	10	##  
这是打印函数 -   ##	7	##  

多返回值

  • Lua可以返回多个结果值,如string.find,返回匹配串“开始和结束的下标”(如果不存在匹配串返回nil)

    >s,e=string.find('www.runoob.com','runoob')   >print(s,e)  
    

    5 10


  • Lua函数中,在return后列出要返回的值得列表即可返回多值

    function maximum(a)
    local mi=1 –最大值索引
    local m=a[mi] –最大值

    for i,val in ipairs(a) do  
    	if val > m then   
    		mi=i  
    		m=val  
    	end  
    end  
    return m,mi   end  
    

    print(maximum({8,10,23,12,5}))

    结果
    23 3


  • return f()这种形式,则返回“f()的返回值”:

    function foo0() end   function foo1() return 'a' end   function foo2() return 'a','b' end  
    

    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 result)
    print(foo(3))
    –(no result)


  • 可以使用圆括号( )强制使调用返回一个值

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

  • 函数多值返回的特殊函数unpack,接受一个数组作为输入参数,返回数组的所有元素。unpack被用来实现范型调用机制,在C语言中可以使用函数指针调用可变的函数,可以声明参数可变的函数,但不能两者同时可变。在Lua中如果你想调用可变参数的可变函数只需要这样:
    f(unpack(a))
    unpack返回a所有的元素作为f()的参数

    f=string.find   a={'hello','ll'}   print(f(unpack(a)))  
    

    –>3 4


预定义的unpack函数是用C语言实现的,也可以用Lua实现

function unpack(t,i)  
	i= i or 1  
	if t[i] then  
		return t[i],unpack(t,i+1)  
	end  
end  

可变参数

  • Lua函数可以接受可变数目的参数,和C语言类似在函数参数列表中使用三点(…) 表示函数有可变的参数。
  • Lua将函数的参数放在一个叫arg的表中,#arg 表示传入参数的个数。

    function average(...)  
    result = 0  
    local arg={...}  
    for i,v in ipairs(arg) do   
    	result = result + v  
    end  
    print('总共传入' .. #arg .. '个数')  
    return result/#arg   end  
    

    print(‘平均值为’,average(10,5,3,4,5,6))

    结果
    总共传入 6 个数
    平均值为 5.5


再论函数

Lua中的函数是带有词法定界(lexical scoping)的第一类值(first-class value)

第一类值

在Lua中函数和其他值(数值、字符串)一样,函数可以被存放在变量中,也可以存放在table中,可以作为函数的参数,还可以作为函数的返回值

词法定界

嵌套的函数可以访问它外部函数中的变量

  • Lua中关于函数难以理解的地方时函数也可以是匿名的。
    函数名(如print)实际上是一个指向函数的变量,像具有其他类型值的变量一样

    a={p=print}   a.p('hello world')   -->hello world  
    

    print=math.sin – print now refers to the sin function

    a.p(print(1)) –>0.841470

    sin=a.p –sin now refers to the print function
    sin(10,20) –>10 20


闭包

当一个函数内部嵌套另一个函数定义时,内部的函数体可以访问外部的函数的局部变量,这种特征我们称作词法定界。虽然这看起来很清楚,事实并非如此,词法定界加上第一类函数在编程语言里是一个功能强大的概念,很少语言提供这种支持。
下面看一个简单的例子,假定有一个学生姓名的列表和一个学生名和成绩对应的表;现在想根据学生的成绩从高到低对学生进行排序,可以这样做:

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  

例子中包含在sortbygrade函数内部的sort中的匿名函数可以访问sortbygrade的参数grades,在匿名函数内部grades不是全局变量也不是局部变量,我们称作外部的局部变量(external local variable)或者upvalue。(upvalue意思有些误导,然而在Lua中他的存在有历史的根源,还有他比起external local variable简短)。

function newCounter()  
    local i = 0  
    return function()     -- anonymous function  
       i = i + 1  
        return i  
    end  
end  
<spa

糖果

糖果
LUA教程

如果不小心安装错 SQL Server 为 Evaluation 的版本,要小心当超过 180 天之后,系统就会无法正常使用了 这几天遇到一个蛮特别的案例,原本收到的问题是 “维护计划” 忽然无法使用,即便是里面没有任何的Task,都无法顺利地执行。但从对方所提供的错误消...… Continue reading

PLUM NIZ静电容键盘怎么样?

Published on September 25, 2020

程序员如何选择合适的机械键盘

Published on September 18, 2020