Lua - 基础类型定义
Posted Lua探索之旅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Lua - 基础类型定义相关的知识,希望对你有一定的参考价值。
静态or动态
在静态类型语言(c/c++、java、c#、golang)里,每个变量必须显式的指定其类型,如下所示:
int a = 1;
string s = "good";
而在动态类型语言(python、lua、php、js)里,不需要为变量指定其类型,如下所示:
a = 1
s = "good"
看上去动态类型更符合用户习惯,用户只需知道value的格式,而不用关心系统内部用什么类型表示。相信每个学过c语言的人,都被指针这个概念迷惑了很久,假如大家一开始学习的是python,我相信会好很多。
静态和动态类型的区别在于类型检查的时机,静态类型一般在编译期执行类型检查,而动态类型在运行时检查类型,这两种方式各有优缺点,这里只说缺点:
静态类型:不够灵活,比如C++严重依赖模板泛型编程,最新的c++11以及后续版本几乎全是泛型编程,传统C++程序员几乎要从精通到重新入门。
动态类型:过于灵活,一段错误代码如果没被执行到,可能运行几个月都没被人发现,调试不便,需要通读代码才能理解程序。
Lua语言是一门典型的动态类型语言,比如定义函数时不需要写参数类型:
function max(a, b)
if a>b then return a end
return b
end
可以看到,动态语言天生具备泛型能力,那么在Lua里如何表示一个变量呢?
Object通用类型
如果能用一种通用类型(比如Object)表达所有类型,那么就相当于为每个变量添加了类型,上面的代码可改写为:
Object a = 1
Object s = "good"
function max(Object a, Object b)
if a>b then return a end
return b
end
假定Object类型是编译器自动添加的,那么就和静态类型一致了。现在的问题是如何用Object表示所有类型?
一个被很多人遗忘的C语言关键字union闪亮登场,union用来表示联合体,多个成员共享一份存储空间,以占用空间最大的成员为实际占用空间。
以数值、字符串、table这3种类型为例,代码如下:
struct Object {
union {
double num;
char* str;
table* tb;
} value;
int type;
};
type存储实际类型
数值用num成员
字符串用str成员
table用tb成员
以最大成员double为准,一个union占用8个字节
这里引出一个新的概念:值类型和引用类型。在C#和java里有这两种概念,值类型一般为基本的int、double、bool等简单类型,引用类型为类、数组、字符串等。
在Lua内部实现里(用户不需要知道这些类型的存在):
值类型包括number、bool、light userdata
引用类型包括string、userdata、closure、table、proto、upvalue、thread
用union结构表示时,值类型使用原始类型,引用类型使用指针,如下所示:
struct Object {
union {
/*值类型*/
double num;
bool b;
void* light_userdata;
/*引用类型*/
string* str;
userdata* udata;
closure* cl;
table* tb;
proto* p;
upvalue* upval;
thread* td;
};
int type;
};
这样就能用一种通用类型Object表达所有类型,且区分值类型和引用类型。
实例分析:
a = 1
s = "good"
对应的内部逻辑为:
Object a, s;
Object obj1;
obj1.type = INT;
obj1.num = 1;
a = obj1;
Object objstr;
objstr.type = STRNG;
objstr.str = new string("good")
s = objstr;
假如要对类型进行扩展,比如支持int64,考虑到int64是值类型,扩展后的Object如下所示:
struct Object {
union {
/*值类型*/
double num;
bool b;
void* light_userdata;
int64_t i64; /* 新增类型 */
/*引用类型*/
string* str;
userdata* udata;
closure* cl;
table* tb;
proto* p;
upvalue* upval;
thread* td;
};
int type;
};
由于int64和double都是8个字节,Object的大小没有增加。
除了union联合体之外,还可以用类继承方式实现通用类型,比如Python就是通过PyObject*表示所有类型,代码如下:
typedef struct _object {
PyObject_HEAD
} PyObject;
typedef struct {
PyObject_HEAD
long ob_ival;
} PyIntObject;
typedef struct {
PyObject_VAR_HEAD
PyObject **ob_item;
Py_ssize_t allocated;
} PyListObject;
可以看到,PyIntObject和PyListObject的第一个字段是PyObject,这样变相实现了C++的继承语法,任何需要类型的地方的都可以用PyObject*代替。
关于动态语言的通用类型介绍到这里,各位有什么想法或建议可以留言哦~~
以上是关于Lua - 基础类型定义的主要内容,如果未能解决你的问题,请参考以下文章