美文网首页
《Lua程序设计》1-8章读书笔记

《Lua程序设计》1-8章读书笔记

作者: 李相赫的乐芙兰 | 来源:发表于2018-11-15 21:32 被阅读41次

    为什么使用lua:
    通常组件表示了一个更具体更底层的概念,在程序开发过程中很少会修改它们,并且它们会占用最终程序的大部分cpu时间。lua则可以连接这些组件,给出一个应用程序最终的样子,而这部分内容可能会在一个产品的开发周期中被反复修改

    程序块:
    一连串的语句或命令

    交互模式下,每行输入的内容自身形成一个程序块,在这种情况下,local的作用域可能与预期的不同

    dofile("xxx.lua") 在交互模式下加载xxx.lua文件

    交互模式下 = 可以直接打印变量的值

    动态类型语言:
    语言中没有类型定义的语法,每个值都携带了它自身的类型信息

    lua将数字0和空字符串也视为“真”

    只要使用双精度来表示的是一个整数,就不会出现浮点数误差问题。当今大多数cpu的浮点数运算速度和整数运算一样快,而有的cpu的浮点运算可能还要更快

    lua的字符串是不可变的值,不能像在C语言中直接修改字符串的某个字符,而要根据修改要求来创建一个新的字符串

    在一个字符串上应用算数操作时,lua会尝试将这个字符串转成数字
    print("10" + 1) -->11
    对数字做字符操作时,也会将数字转换成字符串
    print(10 .. 20) -->1020
    ".."是字符串连接操作符,在一个数字后面输入它时,必须用一个空格来分隔,不然第一个点会被理解成小数点

    table无法声明,通过构造表达式{}创建
    一个持有table的变量是对table的一个引用
    当没有变量引用这个table时,lua的gc会删除该table并复用它的内存

    当table中的某个元素没有初始化时,它的值为nil
    同样可以将nil赋值给某个元素来删除该元素
    a.x等同于a["x"],是一种语法糖

    函数可以存储在变量中,可以通过参数传递给其他函数,还可以作为其他函数的返回值

    对于table、userdata和函数,只有它们引用同一个对象时,才认为它们相等

    and操作:若第一个操作数为假,则返回第一个操作数,否则返回第二个操作数
    or操作:若第一个操作数为真,则返回第一个操作数,否则返回第二个操作数

    max = (x>y) and x or y

    多重赋值
    x,y = y,x -->交换x,y的值
    a,b,c = 0 -->0,nil,nil 数量不对等,没有值的变量会被赋值为nil

    数字型for
    for var=exp1,exp2,exp3 do
    end
    for的3个表达式是在循环的一开始一次性求值的

    泛型for
    for k in pairs(t) do print(k) end
    通过迭代器(如pairs)来遍历table

    break和return只能作为一个程序块的最后一条语句或者是else end until的前一条语句
    如果一定要在某段代码中间插入,则用do break end的形式来使用

    一个lua函数既可以使用lua编写的函数,又可以调用以C语言编写的函数
    例如所有lua标准库中的函数都是用C语言写的。但这些细节对于lua程序员来说是透明的。
    无论一个函数是用lua编写还是用C语言编写,在调用它时没有任何区别

    lua允许函数返回多个结果
    在多重赋值中,若一个函数调用是最后的表达式,那么lua会保留其尽可能多的返回值用于匹配赋值变量,如果不是最后一个元素,则只产生一个值

    可以将一个函数放入一对圆括号中,从而迫使它只返回一个结果

    变长参数
    function add(...)
    local s = 0
    for i,v in ipairs{...}
    s = s + varend
    return s
    end

    lua中的函数与所有其他值一样都是匿名的,即它们都没有名称。当讨论一个函数名是(例如print),实际上是在讨论一个持有某函数的变量

    对于函数的定义
    function foo(x) return 2x end
    实际上是以下代码的一种简化书写方式
    foo = function(x) return 2
    x end
    因此一个函数的定义实际上是一条赋值语句

    当一个函数接受另一个函数作为实参时,称其是一个高阶函数

    闭包:一个函数加上该函数所需要访问的非局部的变量

    do
    local oldSin = math.sin
    local k = math.pi/180
    math.sin = function(x)
    return oldSin(x*k)
    end
    end
    将老版本的sin保存到一个私有变量中,当do end的所用域结束后,就只有新版的sin才能访问它了

    当一个函数调用是另一个函数的最后一个动作时,该调用称为尾调用
    function f(x) return g(x) emd
    在尾调用之后,程序不需要保存任何关于该函数的栈信息。当g返回时,执行控制权可以直接返回到调用f的那个点上
    使得在进行尾调用时不耗费任何栈空间

    迭代器是一种可以遍历一种集合中所有元素的机制
    在lua中通常将迭代器表示为函数,每调用一次函数,返回集合中的下一个元素
    每个迭代器都需要在每次成功调用之间保持一些状态,这样才能知道它所在的位置及如何步进到下一个位置
    一个闭包就是一种可以访问其外部嵌套环境中的局部变量的函数,对于闭包,这些变量就可以用于在成功调用之间保持状态值

    function values(t) --工厂函数
    local i = 0
    return function() i = i + 1;return t[i] end
    end

    t = {10,20,30}
    iter = values(t) --创建迭代器
    while true do
    local element = iter() --调用迭代器
    if element == nil then break end
    print(element)
    end

    泛型for
    t = {10,20,30}
    for element in values(t) dofile
    print(element)
    end
    泛型for在内部保存了迭代器函数

    泛型for语法:
    for <val-list> in <exp-list> do
    <body>
    end
    for做的第一件事是对in后的表达式求值,这个表达式返回3个值供for保存:
    迭代器函数、恒定状态、控制变量的初值

    迭代器并没有做实际的迭代,真正做迭代的是for循环,而迭代器只是为每次迭代提供一些成功后的返回值

    i = 32
    local i = 0
    f = loadstring("i = i + 1;print(i)")
    g = function() i = i + 1;print(i) end
    f() -->33
    g() -->1

    loadstring总是在全局环境中编译它的字符串
    loadstring最典型的用处是执行外部代码,可以让用户输入函数代码,来参与一个函数的定义
    loadstring期望的是输入一个程序块,即一系列的语句,所以要对一个表达式求值,则必须在其之前添加return

    print(debug.traceback())打印当前执行的调用栈

    相关文章

      网友评论

          本文标题:《Lua程序设计》1-8章读书笔记

          本文链接:https://www.haomeiwen.com/subject/adpufqtx.html