lua学习记录

注释
    单行 --
    多行 --[[ ... ]]
变量
    动态类型 类似于python 变量自身没有类型 类型包含在值中
        a=1
        print(type(a))
    变量名类似于c 以字母数字下划线组成 不能以数字开头 大小写敏感
    以下划线开头的变量名或许有特殊作用 如_VERSION 官方不推荐用户定义的变量以下划线开头
    单纯的一个下划线 _ 的变量名常用作dummy variable
基本类型
    nil, boolean, number, string, function, userdata, thread,table
    userdata:用于存储任意的C数据 相当于指定一块完全没操作的内存 用metatable定义操作 其值不能在lua内修改/操作
只能通过c api  
    thread:用于实现lua内的多线程,独立于外部操作系统

关键字
        and    break    do    else
        elseif    end    false    for
        function    if    in    local
        nil    not    or    repeat
        return    then    true    until
        while    goto
字符串
    单行:以'或"作开头结尾 在其中表示引号时需要加相应的\
    多行:[[...]]类似于python
赋值
    可以进行复数赋值 
        a,b,c,d,e=1,2,3,4,5
        a,b,c,d,e=e,d,c,b,a
        print(a,b,c,d,e)
    在赋值前值表的长度会调整为变量表的长度,多的舍弃少的补nil
    若表达式以一个函数调用为结尾 则在调整前完成函数返回(?)
    在开始赋值前 会先将值的内容进行评估(转化为常量?)(避免c的操蛋赋值问题?)
    
符号..
    用在变量名前会得到其值的字符串输出 -存在问题
        a=1
        print(..a)
        print(type(..a))
    用在字符串间起到连接字符串的效果 
        a='b'
        a=..a  --不是所有类型都能这么用--若不是两边都为string 调用concat
        print(a)
    会导致类型转换
        a=1
        print(type(a))
        a=a..a
        print(a)
        print(type(a))

print "string" 可以用于直接输出字符串 不过看起来不能用在变量上 功能是print()的子集

io.write()会在不产生换行符的情况下输出一个字符串 相对的 print()会输出一个单独的换行符

table变量

    类似于list的用法
    a={}
    b={1,2,3}
    c={"a","b","c"}
    d={4,"d"}
    print(a)

    类似于dictionary的用法
    a={}
    a.b="aaa" --成员式增加
    成员可以套娃 但是创建时要逐层套
        a={}
        a.a={}
        a.a.a={}
        a.a.a.a={}
        是可行的
    但是
        a={}
        a.a.a={}是不可行的
    大概确定是指针间操作
        b={}
        a.a=b
        print(a.a)
        print(b)
        b.z="z"
        print(a.a.z)
    此处的赋值可以看见是直接传指针 有出问题的预感
    table还能用[]式的访问
        a.a="123"
        print(a["a"]) 注意[]内的""
        x[]内为数字时可以达到其他语言数组的效果?
        var.name是var["name"]的语法糖
        []内的类型看起来可以是任意的 而.式访问将其限定在了字符串
        
        使用#判断table的长度时,判定依据为t[n]!=nil 且t[n+1]=nil  这只对塞满了的情况有效
        
        a = { [f(1)] = g; "x", "y"; x = 1, f(x), [30] = 23; 45 }
        等同于
        do
           local t = {}
           t[f(1)] = g
           t[1] = "x"         -- 1st exp
           t[2] = "y"         -- 2nd exp
            t.x = 1            -- t["x"] = 1
              t[3] = f(x)        -- 3rd exp
              t[30] = 23
               t[4] = 45          -- 4th exp
              a = t
           end
 


if if...then...elseif...else...end

    a=2
    if a==1 then
        print("asdf")
    elseif a==2 then
        print("fdsa")
    else
        print("lll")
    end

    注意elseif 和else if之间的差别 可能导致判断的分界问题?

判断相关
    lua的不等于符号是~=
    但是好像没有单独的~号?
    用not关键字表示非
    lua有boolean类型
    nil和false被当做否 其余都会被当做真(数字0、空字符串...)
    关于返回值:
        not返回false/true
        and:若第一个值为nil/false 返回这个值 否则返回第二个值 
        or:若第一个值不为nil/false 返回这个值 否则返回第二个值
        

    三目运算符 value = test and x or y
        a=1
        b=(a==1)and "first" or "second"
        print(b)
            
            value= a and b or c
            a=false/nil -> (a and b)=false/nil ->value=c
            a!=false/nil -> (a and b)=b -> value=b
    
while
    a=1
    while a~=5 do
        a=a+1    --看起来lua没有++
        io.write(a.." ")
    end

repeat until
    a=0
    repeat
        a=a+1
        print(a)
    until a==5

for
    for a=1,4 do io.write(a) end
    for a=1,6,3 do io.write(a) end
    开始,结束(包含),步进
    for key,value in pairs({2,4,6,8})do print(key,value) end
    table式步进
    b={a,b,c,d}
    b.a="asf"
    b[true]="false"
    for key,value in pairs(b) do print(key,value) end
    table式步进2
    
break
    a=0
    while true do
        a=a+1
        if  a==10 then
            break
        end
    end

函数
    function关键字
    function aaa()
        print("123")
    end
    aaa()
        -脚本式的共同点:在调用的时候才会发现问题
    return关键字
    function aaa()
        return 123
    end
    a=aaa()
    print(a)
    多输入/多输出  -lua的return可以返回一串
    function aaa(a,b,c)  --如果混入未初始化的变量 会处理作nil 而非报错 同理 删除变量的方法就是将其赋值为nil
        return a,b,c,"123","456","789"
    end
    a,b,c=1,2,3
    a,b,c,d,e,f=aaa(a,b,c)
    print(a,b,c,d,e,f)
    注意 函数内的变量仍然默认为全局 局部变量需要local关键字
    function f() <body> end等同于f=function () <body> end

 
 

    可变参数...
    function printf(fmt, ...)
        io.write(string.format(fmt, ...))
    end
    printf("hello %s from %s on %s \n",os.getenv"USER" or "there", _VERSION, os.date())


    function add(...)  
    local s = 0  
      for i, v in ipairs{...} do   --> {...} 表示一个由所有变长参数构成的数组  
        s = s + v  
      end  
      return s  
    end  
    print(add(3,4,5,6,7))  --->25
    


    #操作符返回字符串长度(?
    
    select("#",...)返回可变参数的长度
    select(n,...)返回第n个参数(包含)到最后一个的串(?) 注意此处开始的下标是1 (lua的计数是从1开始的?



    lua有标准的内置库和外部库
    标准库
    math
    print(math.sqrt(9),math.pi)
    math. abs acos asin atan atan2 ceil cos cosh deg exp floor fmod frexp huge ldexp log log10 max min modf pi
pow rad random randomseed sin sinh sqrt tan tanh
    string
    string. byte char dump find format gfind gsub len lower match rep reverse sub upper
    table
    table. concat insert maxn remove sort
    a={2}
    table.insert(a,3)
    table.insert(a,4)
    table.sort(a,function(v1,v2)return v1 > v2 end)
    for i,v in ipairs(a) do print(i,v) end
    
    io
    io. close flush input lines open output popen read stderr stdin stdout tmpfile type write 
    
    file
    file: close flush lines read seek setvbuf write
    
    os
    os. clock date difftime execute exit getenv remove rename setlocale time tmpname
    
    dofile(filename)打开一个文件将其当做lua chunk执行 返回其结果
    ipairs(t) 返回:迭代器 表t 0   迭代器会从t[1]开始按数字迭代,遇到缺省的键时停止
        pairs(t)则会迭代t中所有键
    load ???
    next(table[,index])返回下一个键值对 可以next(a,next(a))套娃 在遍历时分配新空间的行为是未定义的
    unpack 返回表中元素
    
    

     
    
    外部库 -教程出现毛病 example37

manual
    lua中变量分为local,global,table filed
    lua带有自动的内存回收
    
    函数本身 作为值 是匿名的  函数名的实际情况是持有某个函数的变量
    local var=var 创建一个和全局变量一样名字和值的局部变量 在某些情况下有用
    使用do end块分区有利于local的使用
    交互模式下会将每句输入当做一个chunk 需要时使用do end块
    
    
协程
    与多线程不同 协程只有显式的调用yield才会挂起
    coroutine是一个table
    使用coroutine.create(<function>)创建一个协程会返回其句柄,此时不会执行这个协程
    coroutine.resume(<handle>) 将上面得到的句柄作为参数 第一次使用时 协程会被执行
        其返回值为true/false 表示协程正常执行结束/出现未保护的错误
        当一个协程中含有yield 在resume的执行中 会导致resume的返回 即使这个yield是嵌套的
        这个返回使resume返回true 以及任何传递进coroutine.yield的参数
        对这个句柄继续resume 会使它从上次yield的地方继续执行 这个yield会返回传递给resume的任何附加参数
            a=function()
                print(coroutine.yield("AAA"))
            end
            c=coroutine.create(a)
            print(coroutine.resume(c))
            coroutine.resume(c,"BBB")
    coroutine.warp()也会创造协程,类似于create 但返回值不同 会返回一个函数 这个函数被调用时继续协程 
        任何传递给这个函数的参数会相当于resume的附加参数 其返回值和resume相同,除了第一个的true/false
        它不会像resume那样捕获错误,这些错误会传递给调用者
    function foo (a)
       print("foo", a)
       return coroutine.yield(2*a)
     end
     
     co = coroutine.create(function (a,b)
           print("co-body", a, b)
           local r = foo(a+1)
           print("co-body", r)
           local r, s = coroutine.yield(a+b, a-b)
           print("co-body", r, s)
           return b, "end"
     end)
            
     print("main", coroutine.resume(co, 1, 10))
     print("main", coroutine.resume(co, "r"))
     print("main", coroutine.resume(co, "x", "y"))
     print("main", coroutine.resume(co, "x", "y"))

c API
    lua.h中定义了c与lua的交互
    lua中的函数可能以宏的形式呈现
    使用一个虚拟的栈与c进行值传递 其中的每个元素表示一个lua中的值
    lua调用c时 被调用的函数会获得一个新的栈,与之前的栈、c的函数使用的栈独立
        它初始带有传递给c的参数,被调用的函数会将其结果传递入栈
    为了方便使用,多数api中的查找操作不会遵守严格的栈规则
        使用一个索引,可以任意的指向栈中的元素
        正的索引值表示栈中的绝对位置(从1开始),负的表示距栈顶的偏移
            对于一个含n个元素的栈 1表示栈中第一个元素,n表示最后一个(栈顶)此时-1=n -n=1
    栈的一致性由使用者维护,即栈溢出是可能发生的
        使用lua_checkstack增加栈的大小
        当lua调用c时 它保证LUA_MINSTACK 大小的栈空间可用,它被定义为20,如果不循环的向栈中插入元素,一般是够用的
    伪索引:?
    


closure
    第一类型值(first-class value) 表示与传统类型的值具有相同权利:可以存储在变量/table中 可作为实参传递给函数 作为函数返回值 可运行期间创建
    词法定界:当一个函数内嵌套另一个函数的时候,内函数可以访问外部函数的局部变量,这种特征叫做词法定界
    外部局部变量(external local variable,upvalue)以范例解释

    names = {"Peter", "Paul", "Mary"}
    grades = {Mary = 10, Paul = 7, Peter = 8}

    function sortbygrade (names, grades)
      table.sort(names, function (n1, n2)
        return grades[n1] > grades[n2]
      end)
    end
        
    sort中的无名函数的参数出现了grades 对于其既不是globle也不是local的变量 将其称作upvalue
    
    lua的机制使得函数也可以存储在table中或是作为本地变量
    词法定界使得同一个包内的函数能使用其他的本地函数
    在给本地的函数赋值时,如果其中出现了递归,那么local name=function(...)<>end 会出现问题:
    函数名的定义晚于函数体的赋值,此时函数中的递归会去调用global的同名函数
    赋值前先定义即可
    或者使用语法糖
    local function fact (n)
      if n == 0 then return 1
      else return n*fact(n-1)
      end
    end
    但是此语法糖不会支持间接的递归,所以在间接递归的情况下仍然需要提前定义
    
    lua对尾调用进行了优化
    当一个函数的最后一个指令是调用其他函数,那么在这个调用中不会使用额外的栈空间
    这使得嵌套的尾调用没有数量限制,不会溢出
    function foo (n)
      if n > 0 then return foo(n - 1) end
    end
    这其中的n可以为任意
    
    尾调用的判定需要注意不被算做的情况:
        后接一个不返回return
        return g(x) + 1   需要再做一次加法
        return x or g(x)  需要将比较结果转换为单个返回值
        return (g(x))      括号会将结果转换为单个返回值
    return g(...)的形式才能作为正确的尾调用 不需要位置在文本上的尾部
    不过由于lua在调用前会先处理表达式,g以及其变量可以是复杂的表达式
        return x[i].foo(x[j] + a*b, i + j)
    

generic for/iterator
    lua中使用函数代表迭代器 每次调用时返回集合中的“下一个”元素
    由于closure由函数及其外部本地变量组成 构造一个闭包一般包括两个函数:闭包本身及其构建函数factory
    使用一个迭代器的例子
    function list_iter (t)
      local i = 0
      local n = table.getn(t)
      return function ()
               i = i + 1
               if i <= n then return t[i] end
             end
    end
    
    list_iter作为构建函数 其中的匿名函数则为闭包的函数
    for管理整个迭代循环:
    t = {10, 20, 30}
    for element in list_iter(t) do
      print(element)
    end
    调用factory 在内部保留迭代器函数都由for完成 故不用单独的迭代变量 
    for还完成了每个迭代开始时调用迭代器 在迭代器返回nil时终止循环的操作
    
    一个按词迭代文本的例子:
    function allwords ()
      local line = io.read()  -- current line
      local pos = 1           -- current position in the line
      return function ()      -- iterator function
        while line do         -- repeat while there are lines
          local s, e = string.find(line, "%w+", pos)
          if s then           -- found a word?
            pos = e + 1       -- next position is after this word
            return string.sub(line, s, e)     -- return the word
          else
            line = io.read()  -- word not found; try next line
            pos = 1           -- restart from first position
          end
        end
        return nil            -- no more lines: end of traversal
      end
    end

    其调用方式非常简洁:
    for word in allwords() do
      print(word)
    end
    
    实现思路:使用line pos两个变量记录当前在文本中的位置
        使用'%w+'的正则式描述 一个单词 由string.find完成在目前的行上查找单词的操作 使用string.sub返回这个单词
        
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值