LUA-0 Lua的基本语法

Lua的语法实际上和c的语法很接近,看起来也比较的简洁.(Lua5.1版本)

Lua的关键字如下:

     and       break     do        else      elseif
     end       false     for       function  if
     in        local     nil       not       or
     repeat    return    then      true      until     while

Lua的基本符号如下:

     +     -     *     /     %     ^     #
     ==    ~=    <=    >=    <     >     =
     (     )     {     }     [     ]
     ;     :     ,     .     ..    ...

其中几个与C不同的符号有:  ^符号表示幂运算,例如 12^2,表示12的平方.

#符号针对的是table(表)类型,用于得到table的长度,例如 a = {123,456};print(#a);那么结果会输出2.

~=符号表示 不等于,相当于C语言里的!=.

..符号表示字符串的链接,例如print("d".."e");那么结果会输出de.

...符号则和C语言一样,用于函数的形参,来表示可变参数.

.和:符号其实是一个作用,和C语言中的结构体的使用差不多,例如io.read()和io:read()是一样的,都是调用io下的read()函数.

 

Lua的语法:

1.注释和一些说明

  lua中的注释使用的是--来进行单行注释,和C语言中的//一样只是符号换了个而已.

  lua中的多行注释使用的是--[[ 和 ]],分别和C语言中的/*和*/对应.

  另外lua中的语句的分隔符可以是空格或者分号,也就是说

  a = 123 print(a)语句和a = 123;print(a);两种写法都可以,但还是建议用分号来分隔语句,这样更明确(也更像C了,后面我们使用的所有分号都是基于这个原因).

2.变量

   lua中的变量没有类型,也就是说一个变量可以是任何类型.例如:

   a = 123;-->数值类型

   a = "str";-->字符串类型

   a = [[abc

      def

     ]]

    -->这是字符串的第二种写法,[[和]]中间的内容被视为字符串,且不会解释转义序列,同时如果第一个字符是换行符则无视这个字符.

  a = {"sad",152};-->table(表)类型(表中的数据可以是各种类型),对于任何一个变量,随时可以赋予任意的类型值.

  a = function()

      print("function a");

    end

  -->同样,a也可以是函数类型(函数的具体语法后面会介绍),上面这种写法和下面是一样的:

  

    function a()

      print("function a");

     end

   -->这也引出了lua的一大特色,一切都是变量!

 3.变量类型

   有nil, boolean, number, string, function, userdata, thread, table八种类型.

  nil:本意是0的意思,但是lua将这个作为单独的类型,用于表示不存在.

  nil这个类型需要详细解释,nil作为一种类型,这个类型下的值也只有一个,那就是nil,也就是说,

  如果a = nil;那么就意味着lua中不再存在这个变量了(如果原来这个变量里有值,那么这个变量就会被lua删除);

  同样,访问一个lua中不存在的变量,也会返回nil,例如print(novar);如果前面没有定义novar,那么输出的结果就是nil.

  boolean:有两个值,true和false,用于表示真和假,但是要注意,在判断中,nil也被认为是假,但是false却不能和nil等价.

  在判断中只有false和nil被认为是假!数字0也被认为是true的.

  string:字符串类型

  function:函数类型

  table:表类型,一个表里可以有各种类型的数据,例如a = {123,"sad",function() print(156) end},同样table有自己的索引

  a中的数据可以通过索引访问:例如a[1],a[2],a[3],(注意,lua中下标从1开始).当然也可以自己定义下标:a = {add = 123,sou = "sad"};

  这样就可以通过a.add或者a["add"]来访问其中add表示的数据了.当然,如果下标指向了不存在的地方,那么就会返回nil了.对于table还有

  一点需要注意,a = {[1] = 123,456}这个时候其实a中只有一个值,那就是a[1],值为456.也就是说,在一个表中,lua会按照从前到后的顺序

  对你没有写过下标的数据进行标号,下标从1开始,也就是说,如果你的表中定义了[1] = 123,那么实际上会被lua用456覆盖掉,lua不会检测

  这个下标是否存在.还有一点要说明:在table中,add = 123和["add"] = 123是等价的.

  userdata:用户数据类型(后面再说)

  thread:线程类型(后面再说)

 虽然有各种类型,但是lua中的变量都是由lua来进行类型管理的.

4.逻辑运算符

  and运算符:

    c = a and b;当a为true的时候,c = b,当a为false的时候c = a;

  or运算符:

    c = a or b,当a为true的时候,c = a,当a为false或nil的时候 c = b;

  对于这两个运算符,实际上是逻辑的一种变形,and是逻辑与的变形,or是逻辑或的变形.说是变形是因为他们返回的不是true和false,

  而是参与运算的变量的值.可以这么认为,对于and(逻辑与),首先判断左操作数的的真假,如果为真,那么左操作数就不能决定这个逻辑与

  的真假,而由右操作数决定,因此返回了右操作数.如果左操作数为假,那么这个逻辑与的结果就是假,也就是说,左操作数决定了这个表达式

  的真假,所以返回左操作数.也就是说,按照从左到右的顺序判断操作数的真假,如果该操作数能决定整个逻辑的真假,那就返回这个操作数.

   举个例子:

    a = 1;b = 2;c = nil;e = a and b and c;对于这个式子,首先从左到右,先看a && b,a为真,所以这个这个表达式的真假决定于b,因此

    返回b,于是变成了 e = b and c;同时b && c中,b不能决定表达式的真假,因此由c来决定.所以最后返回c,所以e的值为nil;

  or的逻辑或也可以这样.a = 1;b = 2;c = nil;e = a or b or c;从左到右,a可以决定a || b的真假(此时为真),所以返回a,同理a||c的结果

  也就是a了,所以最后e 的值为1;

  小技巧:a = a or 12;这个用法是当a为假或者nil的时候给a赋值为12.

      a and b or c;这个表达式模拟了c语言中的  a?b:c;的语法.

5.赋值和逻辑控制

  赋值:a  = 8;-->一般赋值

    b,c,d = 45,a,"sdee";-->lua中支持这么赋值,

    a,b = 1;-->当然,如果左边的变量数大于右边的参数数量,就会用nil补齐.所以a = 1;b = nil;

    a = 1,2;-->当右边的参数数量大于左边的变量数量,那么多余的参数就会被舍弃,所以a = 1;

    a,b=b,a;-->交换a和b的值

  if语句:

     if 条件1 then

      代码1

     elseif 条件2 then

      代码2

     else

      代码3

     end;

    -->基本if的结构就是这样了,当然实际使用的时候可以没有elseif和else,但是end不可以少.

  循环语句:

    while 条件 do

      代码

    end;

    repeat

      代码

    until 条件;

   上面两种循环语句和C语言中的while和do...while是一样的.

    for语句:

      一般的for:

       for i = 1,f(x),2 do

        代码

       end;

      -->这是一种十分一般的用法,i=1表示i是控制变量,1是初始值,f(x)实际上是调用f()函数,并把函数的返回值作为循环的终止值

      (也就是当i变量到这个值的时候循环就终止了,函数只在开始循环的时候调用一次),当然终止值也可以直接使用一个数字.最后的2

      表示每次循环i的增量(当然-2也是可以的,如果这个增量省略不写的话,那么默认是1);

     泛型for:

       a = {x = 66,"dsad",554,[5] = 444};

       for i,v in ipairs(a) do
         print(i,v);-->print()函数可以接受任意的参数数量,然后在一行中输出,中间用制表符分隔;
       end;

      ->ipairs()函数会返回a表中的数字下标和对应的值.这个需要特别说明:这个函数实际上是一个闭包(这个概念会在后面说明),暂时

       不用管这个概念,我们只要知道i会是a表中的下标,v是a表中对应下标的值就行.注意,这个下标的限制,这个下标只从1开始,到某

       个下标对应的值为nil的时候终止.也就是说,实际上输出的是:

                     1  dsad

                     2  554

        只会输出两行,也就是说x是不会被输出的,同时下标5的也不会输出,因为到下标为3的时候值已经是nil了(即不存在).     

       for i,v in pairs(a) do
         print(i,v);

       end;

       但是如果我们把ipairs()函数改成pairs()函数就不一样了.

        输出如下:

          1  dsad
          2  554
          5  546
          x  66

        所有的下标和值都会被输出来(注意一下顺序,也就是说数字下标会先输出,而非数字下标后输出,即使x定义在最前面).

   块的概念:

    do

      代码

    end

   do...end中间就是一个区块,本身并没有太大的作用,但是在某些情况下,例如,如果你想定义一个a,这个a只在某个代码块中被用到,但是你

   不想在其他地方被访问到,那么你就可以把你的a和循环都写在这个do...end块中.例如:

      do
        local a = 0;
        --你的代码
      end; 

   这样的话  a就只能在这个do...end中被访问到了.当然a的定义前面要加上local来表示是局部变量(这个局部区域就是这个块).

    当然,没有声明为local的变量就是全局变量了.

6.函数和闭包

  函数的基本写法前面介绍变量的时候已经说过了.只不过我们通常采用下面这种方式来声明函数:

    function func(a,b)
       print(type(a),type(b));-->type()函数用于输出参数的类型

      return a,b;
    end;

  基本的函数就是这样,有参数,有返回值.但是要注意一点,如果你调用这个函数的时候,fun(123,"de",555);如果你给出的参数比函数的参数

  要多的话,那么多出的参数会被无视掉.当然如果你给出的参数少了,就会用nil来填补.另外注意一点,lua的函数是可以返回多个值的,只要中间

  用逗号分隔就行.对于返回值也一样,a,b,c = func(...),这个函数返回了两个数据,但是用于接受的有三个变量,此时c会用nil来填充.用于接受

  的变量如果比返回值少,那么返回值的顺序给变量赋值,多出的返回值被丢弃.注意:函数可以没有返回值,可以不写return.

   lua的函数也支持可变参数:

    function func(a,b,...)
       for i,v in ipairs(arg) do
          print(i,v);
       end;
    end;

    -->...表示可变参数,但是实际上,这个可变参数会被视为一个arg表,因此我们可以用循环的方式来读取每个arg表中的数据,上面的代码

      中i就是参数的编号,从1开始,v就是数据.但是注意,a和b不属于arg表.

   闭包:

    先来看看嵌套的函数:

      function func(a,b)
         function u()
            print(a,b);
         end
         u()
      end;

    首先我们在func()函数内定义了u()函数,然后调用u()函数,仔细看,u函数可以调用func的变量!

    于是闭包就是:

      function func(a,b)

        c = 12;
         return function()
               print(a,b,c);
             end;
      end;

    将函数返回!被返回的函数可以访问func的a,b,c变量,如果调用很多次func函数,都有自己的a,b,c变量,他们之间不会互相干扰,就像

    之前说到的他们是块中的局部变量,这个变量是可以改变的.

  闭包与泛型for:

    for i,v in ipairs(a) do

      代码

    end;

    此处的ipairs()函数实际上就是返回一个闭包函数,而且for循环在每次循环之前都会调用这个闭包函数,以取得i和v的值.返回的闭包函数的原理基本是这个样子:使用之前说到的局部变量来保存遍历到的下标,然后判断下标对应的值是不是nil,如果是的话就返回nil以中止循环,否则就返回下标和对应的值.(这里的for循环实际上是判断返回值是不是nil来确定是否停止循环,是nil则停止循环).

 

7.协程(纤程,Fiber)

    以这个函数为例:

      function func(a,b)
         print(a,b);
         c,d = coroutine.yield(a,b); 
         print(c,d);
         return c;
      end;

    首先说明一下协程的建立:

    co = coroutine.create(func);-->这里的co的类型实际上就是前面提过的thread类型!

    当这么做以后,func()并不会执行,而是出于挂起的状态,然后调用:
    m,n = coroutine.resume(co,1,123);-->注意,这里的1和123就会作为函数的参数!

    则可以使函数开始执行,当函数执行到c,d = coroutine.yield(a,b); 这一句的时候就会暂停,然后将a,b返回,然后继续挂起.

    这时候,m和n的值实际就是函数里传出来的a和b的值了.然后我们继续调用:

    coroutine.resume(co);-->这里我们不传参数

    然后就会从刚才暂停的地方继续执行!然后将传入的值赋值给c和d,但是由于我们没有传值,所以两个变量都是nil.然后直到函数执行

    结束,因为我们在函数里只放了一个yield()函数(当然可以放很多个的).执行结束之后,函数就处于终止状态了.

    上面我们所说的这个co实际上就是协程,而这个协程的函数就是func.    

    如果在某个时刻,我们想知道协程的状态,可以调用coroutine.status(co);以获得状态.
 

 

 

 

转载于:https://www.cnblogs.com/nightfire/articles/2622823.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值