当前位置: 首页 > news >正文

Lua中 'local xxx do ... end' 到底表达了什么

前言

在一些lua的项目中偶尔会发现local xxx do ... end这种写法,那么这种写法有什么作用,或者说这么写又有什么好处呢?下面我们来逐步分析一下。

分析

首先实际代码中的写法可能看起来是这样的:

local subBlock do

function func1( ... )
    -- body
end

name = "test"
local array = {1, 2, 3, 4}

end

print("name =", name)
print("array =", array)

我们知道,其实do ... end就是执行了一个语句块,并没有什么特殊的含义,它基本上等同于C/C++中的{},需要注意的是在这个{}之间的局部变量,在这个区域之后的位置是没有办法引用的,在lua中也是一样的,只不过在lua中可以随意的定义全局变量,所以在do ... end之间的定义的全局变量,在语句块之后也可以引用。

因此执行上述lua代码的结果如下:

name = test
array = nil

那么subBlock这个变量和这个语句块有什么关系呢?subBlock看起来很像是这个语句块的名字,实际实测发现并没有什么关系,实际上这就是已定义了一个局部变量,并且在后面执行了一个语句块,除此之外貌似毫无关系。

我们可以写成这样:

local a
do
    print("test1")
end

还可以写成这样:

local a = "test2"
do
    print("a =", a)
end

甚至是这样:

local a, b, c = "test3", 1, 0
do
    print("a =", a)
end

看到这里是不是发现’local xxx do … end’这个结构很简单的,可是这个local 还可以和’do … end’产生关系,比如像下面这样:

local block
do
    local a = 1
    function block()
        print("a =", a)
    end
    print(block)
end

说到这里,local又和do ... end产生了联系,那么这个block函数到底是局部函数还是全局函数呢?我们下来看看下面的例子:

local function func1()
    function func2()
        -- body
    end
    print("call func1 ...")
end

上述代码中的func1函数明显是一个局部函数,那func2函数到底是一个局部函数和全局函数呢?我们知道全局的变量和函数可以在_G中查到,利用这个特点我们可以测试一下,写出如下代码:

local function func1()
    function func2()
        -- body
    end
    print("call func1 ...")
end

print("func1 =", _G["func1"])
print("func2 =", _G["func2"])

运行的结果如下:

func1 = nil
func2 = nil

有没有很惊奇func2居然不是全局函数,会不会是我们漏掉了什么,我们运行一下func1函数试试,写出如下测试代码:

local function func1()
    function func2()
        -- body
    end
    print("call func1 ...")
end

print("func1 =", _G["func1"])
print("func2 =", _G["func2"])
func1()
print("func1 =", _G["func1"])
print("func2 =", _G["func2"])

运行的结果如下:

func1 = nil
func2 = nil
call func1 …
func1 = nil
func2 = function: 0057E330

看来这次比较符合预期,func2是一个全局函数,只不过需要运行fucn1之后才能有定义。

那么现在我们回过头来看一下这个例子:

local block
do
    local a = 1
    function block()
        print("a =", a)
    end
    print(block)
end

print("block =", _G['block'])

实际上你如果认真看了前面的分析,你会发现这与在函数中定义函数的例子是不一样的,这仅仅在定义了一个局部变量之后又定义了一个同名的函数而已,那是不是函数block会覆盖局部变量block而变成全局函数呢?答案是否定的,我们知道function block()只是block = function()的语法糖,所以看到这里你或许已经明白了,block最终就是一个局部函数,运行结果如下:

function: 001DFD68
block = nil

结论

  1. local xxx do ... end这种表达方式只是一种定义局部变量和执行一个语句块的组合,没有其他特殊含义。
  2. 遇到类似的问题只需要一步一步跟踪就能发现真相。

相关文章:

  • Python树形打印目录结构
  • 排序算法系列之(二)——冒泡排序名字最为形象的一个
  • Python查找文件中包含中文的行
  • sscanf类似于正则表达式的进阶用法
  • mysql函数扩展之UDF开发
  • Python实现一个简单的图片爬虫
  • 验证mysql联合索引最左原则
  • Mysql查询时case when语句的使用
  • Vim中简单格式化代码
  • Vim、Xshell、远程终端莫名卡死的原因
  • 关于游戏中仓库类的设计
  • .bat批处理(五):遍历指定目录下资源文件并更新
  • 神秘莫测的时间复杂度
  • 排序算法系列之(三)——略显神秘的快速排序
  • .bat批处理(六):替换字符串中匹配的子串
  • 2018以太坊智能合约编程语言solidity的最佳IDEs
  • 77. Combinations
  • Cumulo 的 ClojureScript 模块已经成型
  • ERLANG 网工修炼笔记 ---- UDP
  • ES学习笔记(10)--ES6中的函数和数组补漏
  • Flannel解读
  • JavaScript工作原理(五):深入了解WebSockets,HTTP/2和SSE,以及如何选择
  • JavaScript函数式编程(一)
  • leetcode388. Longest Absolute File Path
  • MyEclipse 8.0 GA 搭建 Struts2 + Spring2 + Hibernate3 (测试)
  • PaddlePaddle-GitHub的正确打开姿势
  • PHP 小技巧
  • 解决jsp引用其他项目时出现的 cannot be resolved to a type错误
  • 聊聊flink的TableFactory
  • 前端知识点整理(待续)
  • 让你成为前端,后端或全栈开发程序员的进阶指南,一门学到老的技术
  • 最近的计划
  • 【干货分享】dos命令大全
  • 3月27日云栖精选夜读 | 从 “城市大脑”实践,瞭望未来城市源起 ...
  • 整理一些计算机基础知识!
  • ​如何防止网络攻击?
  • !!【OpenCV学习】计算两幅图像的重叠区域
  • (3)选择元素——(14)接触DOM元素(Accessing DOM elements)
  • (4) PIVOT 和 UPIVOT 的使用
  • (env: Windows,mp,1.06.2308310; lib: 3.2.4) uniapp微信小程序
  • (Pytorch框架)神经网络输出维度调试,做出我们自己的网络来!!(详细教程~)
  • (超简单)构建高可用网络应用:使用Nginx进行负载均衡与健康检查
  • (附源码)springboot宠物医疗服务网站 毕业设计688413
  • (附源码)springboot工单管理系统 毕业设计 964158
  • (亲测成功)在centos7.5上安装kvm,通过VNC远程连接并创建多台ubuntu虚拟机(ubuntu server版本)...
  • (十八)SpringBoot之发送QQ邮件
  • (四) Graphivz 颜色选择
  • (原創) 人會胖會瘦,都是自我要求的結果 (日記)
  • (转) Android中ViewStub组件使用
  • (转)母版页和相对路径
  • .gitignore文件设置了忽略但不生效
  • .NET MVC第三章、三种传值方式
  • .net websocket 获取http登录的用户_如何解密浏览器的登录密码?获取浏览器内用户信息?...
  • .net项目IIS、VS 附加进程调试
  • .Net转Java自学之路—基础巩固篇十三(集合)