SHL

得陇复望蜀
在学习DL性能优化的学生
© 2018. All rights reserved.

lua学习入门

Mac下安装 lua

brew作为Mac下非常好用的包管理工具,可以直接 install lua。直接在Mac终端输入 brew install lua ,lua就安装好了。成功后可以测试一下,执行命令 lua 进入 lua 脚本环境

> print('hello world')
hello world

lua 一些常用名词

在看torch的代码中,我经常可以看到 require, ..等单词或符号,直接看教程有很多语法都是不太用得到的,所以下面我自己整理一下一些常见的语法。

require

require与 C 和 C++ 中的#include类似,还有 python 中的import也是相同的功能,加载模块,加载了模块就可以使用模块的全局函数和全局数据。

require搜索的路径是存在一个全局table package的path和cpath字段里的。

  > print(package.path)
  /usr/local/share/lua/5.3/?.lua;  
  /usr/local/share/lua/5.3/?/init.lua;  
  /usr/local/lib/lua/5.3/?.lua;  
  /usr/local/lib/lua/5.3/?/init.lua;  
  ./?.lua;  
  ./?/init.lua  

  > print(package.cpath)
  /usr/local/lib/lua/5.3/?.so;/usr/local/lib/lua/5.3/loadall.so;./?.so

可以看到默认的路径的格式为: ?.lua , 所以我们require “xxx”,而不是require “xxx.lua”,lua编译器会自动替换“?”

当我们想要加载当前脚本的上级目录时,我们自己可以添加相对路径。

package.path = package.path .. ';..\\?.lua'

require “xxx” 某个模块后

  1. 如果该模块自身有返回值,且模块加载成功,那么require 的返回值就是该模块的返回值
  2. 如果模块没有返回值,如果require加载模块成功,就返回ture
  3. require 内部将返回值储存在:package.loaded表中。 (即:package.loaded[xxx]中)
1. test.lua
local temp = {}
function temp.show()
    print('it\'s ok')
end

return temp

2. ok.lua
local a = require('test')
a.show()

> lua ok.lua
it's ok

..

作为动态语言,lua 同 python 类似,可以直接将字符串连接起来,在 python 中是用+,而 lua 中则用..,对于 C++ 来说,lua 就是将..符号重载了,使其具备了 concat 的功能。

> a = 'a'
> b = 'b'
> a .. b
ab

local

前面不加前缀的变量都是全局变量,local 声明变量为局部变量,但是如果该变量在全局环境中在使用上几乎等价于全局变量。不过一般都推荐使用局部变量,因为 lua 自身的特性,局部变量在加载使用时要比全局变量快很多,详情可以点击这里

a = 4                 -- 全局变量
local b = 5           

function pd()
    local c = 5       -- 局部变量
    d = 5             -- 全局变量
    print(b)          -- 5
end

pd()
print(b, c, d)        -- 5, nil, 5

do
    local a = 6       -- 局部变量
    b = 6             -- 全局变量
    print(a, b)
end

print(a, b)           -- 4,6

一些 lua 的语法

那些与C、C++、Python语法类似的 lua 语法就不再论述了,下面只给自己备忘一些与众不同的语法。

注释语法

在 lua 中注释是用--,就类似于C语言中的//,而块注释的话就将块包括在--[[ --]]

函数类语法

在 lua 中也提供了类似C结构体,C++类的模式,一个变量可以拥有它自己的函数。而且 lua 有两种给变量定义函数的方法

local a = {}
function a.show()
    print('hello world')
end

local b = {}
function b:show()
    print('hello world')
end

冒号: 和点.

:. 其实没有本质的区别,冒号相比于点只是起了一个省略 self 的功能。

ID = { number = 10 }
function ID:SetNumber(num)
    self.number = num
end

function ID.SetNumber(self, num)
    self.number = num
end

用冒号调用时,会隐式地传入self,所以其实冒号调用上面用点定义的函数其实也是可以的。
ID:setNumber(100)
print(ID.number)            --100

当然,不一定就要用self,也可以用其他单词来表示,只是一个别名,下面的方法等价于上面这种方法。
function ID.SetNumber(girl, num)
    girl.number = num
end