Lua
本文是以读者了解Lua基本语法为基础展开的。
Lua是一种轻量语言,它的官方版本只包括一个精简的核心和最基本的库。这使得Lua体积小、启动速度快。
它用标准C语言编写并以源代码形式开放,编译后仅仅一百余K,可以很方便的嵌入别的程序里。
和许多“大而全”的语言不一样,网路通讯、图形界面等都没有默认提供。但是Lua可以很容易地被扩展:由宿主语言(通常是C或C++)提供这些功能,Lua可以使用它们,就像是本来就内置的功能一样。
事实上,现在已经有很多成熟的扩展模块可供选用。wiki
我对Lua理解: Lua是一种多重编程范式
的程序设计语言
- 函数式语言的特性(函数可以当变量传递、动态类型等)
- 提供元表(table) 而不是特定的编程范式(可以用元表模拟各种语言特性)
1. 函数式语言的特性
我们先来看一个c++的 proxy模式
class OperatorBase
{
public:
virtual int operator()(int,int) = 0;
};
class Add: public OperatorBase
{
public:
int operator()(int a, int b)
{
return a+b;
}
};
class Sub: public OperatorBase
{
public:
int operator()(int a, int b)
{
return a-b;
}
};
class Proxy
{
public:
Proxy(OperatorBase& op):_op(op){}
int operator()(int a, int b)
{
return _op(a,b);
}
private:
OperatorBase& _op;
};
int main()
{
Add add;
Sub sub;
Proxy proxy_add(add);
Proxy proxy_sub(sub);
std::cout << "1 + 2 = " << proxy_add(1, 2) << std::endl;
std::cout << "1 - 2 = " << proxy_sub(1, 2) << std::endl;
}
同样的逻辑用lua代码来实现
function add(a, b)
return a+b;
end
function sub(a, b)
return a-b;
end
function proxy(op, a, b)
return op(a, b)
end
print("1 + 2 = ".. tostring(proxy(add, 1, 2)));
print("1 - 2 = ".. tostring(proxy(sub, 1, 2)));
学习这种思想 而不是套用面向对象的设计模式 用c++实现(c++11 或者boost)
include <functional>
int add(int a, int b)
{
return a+b;
}
int sub(int a, int b)
{
return a-b;
}
typedef std::function<int (int,int)> OperFunc;
int proxy(OperFunc& f, int a, int b)
{
return f(a, b);
}
int main()
{
OperFunc f_add = &add;
OperFunc f_sub = ⊂
std::cout << "1 + 2 = " << proxy(f_add, 1, 2) << std::endl;
std::cout << "1 - 2 = " << proxy(f_sub, 1, 2) << std::endl;
}
2. 元表来模拟面向对象
Lua 中实现面向对象 云风博客
local _class={}
function class(super)
local class_type={}
class_type.ctor=false
class_type.super=super
class_type.new=function(...)
local obj={}
do
local create
create = function(c,...)
if c.super then
create(c.super,...)
end
if c.ctor then
c.ctor(obj,...)
end
end
create(class_type,...)
end
setmetatable(obj,{ __index=_class[class_type] })
return obj
end
local vtbl={}
_class[class_type]=vtbl
setmetatable(class_type,{__newindex=
function(t,k,v)
vtbl[k]=v
end
})
if super then
setmetatable(vtbl,{__index=
function(t,k)
local ret=_class[super][k]
vtbl[k]=ret
return ret
end
})
end
return class_type
end
这个lua oop的用法
定义基类
base_type=class() -- 定义一个基类 base_type
function base_type:ctor(x) -- 定义 base_type 的构造函数
print("base_type ctor")
self.x=x
end
function base_type:print_x() -- 定义一个成员函数 base_type:print_x
print(self.x)
end
function base_type:hello() -- 定义另一个成员函数 base_type:hello
print("hello base_type")
end
继承
test=class(base_type) -- 定义一个类 test 继承于 base_type
function test:ctor() -- 定义 test 的构造函数
print("test ctor")
end
function test:hello() -- 重载 base_type:hello 为 test:hello
print("hello test")
end
用法
a=test.new(1) -- 输出两行,base_type ctor 和 test ctor 。这个对象被正确的构造了。
a:print_x() -- 输出 1 ,这个是基类 base_type 中的成员函数。
a:hello() -- 输出 hello test ,这个函数被重载了。
3. lua c/c++接口
这部分主要是宿主程序跟 Lua 通讯用的一组 C 函数。 所有的 API 函数按相关的类型以及常量都声明在头文件 lua.h 中。lua 5.1
总结:
不管是lua中调用c 还是在c中调用lua 他们之间数据的传递是依靠Lua的函数栈来实现的。
4. coroutine 协程
目前多任务机制大致上分为两种:抢占式(比如多线程 由线程调度来决定那个任务占用cpu),协同式(由任务自身决定如何分配cpu)
据几个例子(并不是指协程而是值协同式的任务机制):google javascript V8, 网络编程中的event loop(nginx、netty)等
协程的用途:
实现状态机,提高代码可读性
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"))
运行结果:
co-body 1 10
foo 2
main true 4
co-body r
main true 11 -9
co-body x y
main true 10 end
main false cannot resume dead coroutine