美文网首页
lua学习之深入函数第二篇

lua学习之深入函数第二篇

作者: 跃千山 | 来源:发表于2020-02-26 20:56 被阅读0次

深入函数 2

非全局的函数

  1. 函数是第一类值,函数可以存储到全局变量,局部变量,table 字段中
  2. lua 函数库中的大部分函数存储到 table 字段中
Lib = {}
Lib.foo = function (x, y)
    return x + y
end
Lib.goo = function (x, y)
    return x - y
end
Lib = {
    foo = function (x, y) return x + y end,
    goo = function (x, y) return x - y end
}
Lib = {}
function Lib.foo(x, y) return x + y end
fucntion Lib.goo(x, y) return x - y end
  1. 将一个函数存储到一个局部变量中,即为「局部函数」
  2. 该函数只能在对应的作用域使用,对于「程序包」package 很有用
  3. lua 将每一个程序块当作一个函数来处理
  4. 在程序块中声明的函数就是局部函数,只在该程序块中可见
  5. 词法域确保了程序包中的其他函数可以使用这些局部函数。
local f = function (<参数列表>)
    <函数体>
end

local g = function (<参数列表>)
    <函数代码>
    f(实参) -- 可以调用 f
    <函数代码>
end

local function f(<参数列表>)
    <函数体>
end

-- 阶乘 n! = n * (n - 1) * (n - 2) * ... 1
local fact = function (n) -- 错误的递归函数定义
    if n == 0 then 
        return 1
    else
        return n * fact(n - 1) -- fact 函数定义未完成,调用的是 fact 全局变量,而不是 fact 函数本身
    end
end
    
-- 正确的递归函数定义
local fact
fact = function (n)
    if n == 0 then
        return 1
    else
        return n * fact(n - 1)
    end
end

local function foo(<参数>) <函数体> end
-- Lua 将其展开为:
local foo
foo = function (<参数>) <函数体> end
-- 正确的函数定义,对于间接递归无效
local function fact (n)
    if n == 0 then
        return 1
    else
        return n * fact(n - 1)
    end
end
-- 递归就是函数调用函数本身
-- 间接递归就是 a 函数调用 b 函数而 b 函数又调用了 a 函数
-- 间接递归需要使用明确的前向声明
local f, g
function g ()
    <函数代码>
    f()
    <函数代码>
end

function f() -- 不要加 local 如果加上那么在函数 g 中引用的就处于未定义状态,因为 lua 会创建一个全新的局部变量 f
    <函数代码>
    g()
    <函数代码>
end

正确的尾调用

  1. 「尾调用」是类似于 goto 的函数调用
  2. 当一个函数调用是另一个函数的最后一个动作时,该调用就是一条「尾调用」
function f (x)
    <函数代码>
    return g(x)
end
  1. f 调用完 g 之后就没有执行其他代码了
  2. 在这种情况下,程序就不需要返回「尾调用」所在的函数了
  3. 在「尾调用」之后,程序无需保存任何关于该函数的栈信息
  4. 当 g 返回时,执行控制权可以直接返回调用 f 的那个点上
  5. 使得在进行「尾调用」时不耗费任何栈空间
  6. 这种实现称为「尾调用消除」
-- 尾调用函数
function foo(n)
    if n > 0 then
        return foo(n - 1)
    end
end
-- 调用完 g 函数后还进行了加法操作,非尾调用
return g(x) + 1 
-- 有 or 操作,必须调整为一个返回值
retrun x or g(x) 
-- 函数外嵌套一个括号,强制其只返回一个返回值
return (g(x))
-- 尾调用标准格式
return <func>(<args>)
-- 是一个尾调用
-- 调用前会对 <func> 及其参数求值
return x[i].foo(x[j] + a * b, i + j)

编写状态机

  1. 典型例子:迷宫
-- 四间房间的迷宫
function room1()
    local move = io.read()
    if move == "south" then
        return room3()
    elseif move == "east" then
        return room2()
    else
        print("invalid move")
        return room1()
    end
end

function room2()
    local move = io.read()
    if move == "south" then
        return room4()
    elseif move == "west" then
        return room1()
    else
        print("invalid move")
        return room2()
    end
end

function room3()
    local move = io.read()
    if move == "north" then
        return room1()
    elseif move == "east" then
        return room4()
    else
        print("invalid move")
        return room3()
    end
end

function room4()
    print("congratulations!")
end
  1. 若没有「尾调用消除」,每次用户移动都会创建一个新的栈层,若干步后可能会栈溢出
  2. 「尾调用消除」多用户移动的次数没有任何限制
  3. 因为每次移动实际上只是完成一条 goto 语句到另一个函数

相关文章

  • lua学习之深入函数第二篇

    深入函数 2 非全局的函数 函数是第一类值,函数可以存储到全局变量,局部变量,table 字段中 lua 函数库中...

  • lua入门笔记 目录

    lua的中文API lua入门笔记1 类型 表达式 语句 函数lua入门笔记2 深入函数 深入函数 迭代器与泛型f...

  • Lua学习笔记(5)——深入函数

    1.函数是一种“第一类值”,他们具有特定的词法域。 2.第一类值,表示Lua中函数与其他类型的值(例如数字)具有相...

  • lua学习之函数篇

    函数 函数是对语句和表达式进行抽象的主要机制 两种用法 一是可以完成特定的任务,一句函数调用被视为一条语句 二是以...

  • lua学习之深入函数第一篇

    深入函数第一篇 函数是第一类值,具有特定的词法域 第一类值 第一类值的意思是函数与 lua 中的其他类型如数字,字...

  • Lua中的CAPI概述

    头文件lua.h: Lua提供的基础函数,包括创建Lua环境,调用Lua函数,读写Lua环境中的全局变量,以及注册...

  • JS函数charCodeAt的Lua实现

    JS函数charCodeAt的Lua实现 charCodeAt by Lua @(Lua JavaScript ...

  • Lua base print()

    前言 今天来看一个我们学习lua以来最熟悉的一个函数——打印函数,这个函数可以说是我们写lua代码时,每天都会用到...

  • Lua_API lua_call & lua_callk

    开篇 今天来简单了解一下 Lua 的函数调用:lua_call。 解析 函数调用协议 void lua_call ...

  • 前端MV*框架之MVP

    一、学习背景 本文是继“前端MV*框架之经典MVC”的第二篇,学习动机是通过深入理解MVC、MVP、MVVM后,找...

网友评论

      本文标题:lua学习之深入函数第二篇

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