Lu功能特点
目 录
1 什么是Lu |
3 Lu是一个轻量级的动态库 |
4 Lu可对字符串表达式直接编译运行 |
5 Lu语法简洁,是一种字符流,可自定义注释 |
6 Lu有很高的运行效率 |
7 Lu有五种变量 |
8 Lu有丰富的运算符和数据类型 |
9 Lu支持自定义数据类型和运算符重载 |
10 Lu支持模块化编译,支持对私有数据的保护 |
11 Lu使用命名空间避免函数重名 |
12 Lu有很强的扩展性 |
13 MLu简化了Lu脚本的使用 |
14 Lu提供自动内存管理,也可以手动管理内存 |
15 Lu混合编程中对象操作特点 |
16 Lu支持协程 |
17 Lu是动态强类型的 |
18 Lu支持中文编程 |
19 Lu是可移植的 |
Lu是一个可对字符串表达式进行动态编译和运行的动态链接库(dll),是一种易于扩展的轻量级嵌入式脚本,提供自动内存管理,也可以手动管理内存。Lu有丰富的运算符和数据类型,大多数运算符可进行重载。Lu的优势在于简单易用和可扩展性强。Lu可用于各类数学软件的设计,也可用作报表处理、web、组态软件、游戏等的脚本,具有很高的执行效率。
Lu用stdcall调用协议输出了动态库函数,可供C/C++、VB、delphi、FORTRAN等程序使用。
语法参考:Lu脚本教程。
下载试用:lu64.rar 。
2 在软件中加入脚本支持 [返回页首]
很多软件中提供了脚本支持,例如Excel、Word中使用了VBA;Matlab、Mathematica、MapLe等数学软件中有自己的内嵌脚本;魔兽世界等许多游戏中使用了Lua脚本;组态软件中常使用VBA、JavaScript等脚本;... ...。
通常,应用程序通过窗口提供菜单、按钮、鼠标操作供用户选择功能,如果这些不能满足要求,就需要借助于脚本了。利用脚本语言进行功能扩充和二次开发是未来软件开发的趋势。
脚本的表现形式是字符串(或者说脚本表现为一行或多行字符),这是脚本在软件设计中受欢迎的根本原因。
3 Lu是一个轻量级的动态库 [返回页首]
Lu是一个动态链接库(dll),在64位windows平台上是lu64.dll,lu64.dll称为Lu的核心库 ,大小约250K~300K,是轻量级的。Lu用stdcall调用协议输出了动态库函数,可供C/C++、VB、delphi、FORTRAN等程序使用。Lu提供了约30多个输出函数,但常用的只有几个。使用Lu的输出函数相当于进行API(Application Program Interface)函数调用。
4 Lu可对字符串表达式直接编译运行 [返回页首]
许多脚本语言需要将脚本文件保存为磁盘文件才能调用,例如Lua脚本文件的扩展名为“.lua”,Python脚本文件的扩展名为“.py”,Matlab脚本函数的扩展名为“.m”,等等。虽然这些脚本也能直接编译运行字符串形式的表达式,但通常会有这样或那样的限制,或者效率较低。
Lu可对Unicode字符串表达式(字符串中可定义一个函数)直接编译运行。Lu的输出函数中,LuCom用于编译一个字符串,返回一个句柄p;LuCal用于执行句柄p,可执行任意多次。注意这里所说的编译与C/C++的编译不同,Lu的编译是将字符串表达式编译为LuCal可执行的中间代码。
参考:Lu编程指南。
简单的Lu表达式:
1+2
定义一个函数f,恐怕是所有语言中最简单的了:
f(x,y)=x+y
函数调用:
f(1,2)
可使用三对等价的括号( )、[ ]和{ }以增强可读性:
f(x)=x^3*ln{abs[(x^2-1)*(x^2-2)]}
可使用三个等价的逗号、冒号或分号分隔语句以增强可读性,以下new函数生成二维数组(矩阵)并赋初值:
new[reals,3,2, data : 1.1,2.2; 3.3,4.4; 5.5,6.6]
所有的Lu代码都是字符串形式,称为字符串表达式,字符串表达式中可定义一个函数,例如前面定义的函数f。
类似于C/C++,Lu代码是一种字符流,该字符流是由逗号隔开的若干语句组成,例如下面定义的函数test(这是一段有关八皇后问题的代码,不理解没有关系):
test(row, ld, rd : pos,p : sum,upperlim)=
{
which
{
row != upperlim,
{
pos = {upperlim && [!!(row||ld||rd)]},
while{ pos,
p = pos&&(-pos),
pos = pos -p,
test[row+p, (ld+p)<<1, (rd+p)>>1]
}
},
sum++
}
}
也许你发现似乎有些地方缺少逗号,但这是一种错觉,注意test、which、while是函数,其余的标识符row、ld等是各种变量,另外,最后一个语句后是不能有逗号的。
该函数可在一行中进行定义:
test(row, ld, rd : pos,p : sum,upperlim) = {which{row != upperlim, {pos = {upperlim && [!!(row||ld||rd)]},while{ pos,p = pos&&(-pos), pos = pos -p, test[row+p, (ld+p)<<1, (rd+p)>>1] }}, sum++ }}
很遗憾,核心库lu64.dll支持的Lu源代码中不能包含注释,不过,这个缺点恰恰也是Lu的优点,你可以自己定义注释的形式,在用LuCom编译源代码之前,自己去掉注释即可(将注释字符全部用空格代替)。
个人比较喜欢C++风格的注释,故在Lu模块化编译运行库MLu中使用了这种注释。
参考:Lu用户指南。
6 Lu有很高的运行效率 [返回页首]
参考1:Lu与C/C++、Forcal、MATLAB、Python、Lua等各种语言的速度比较。
参考2:Lu与Lua运行速度比较。
在主程序和Lu系统之间频繁穿越时,仍有很高的效率,参考:C/C++调用Lu脚本函数。
Lu有五种变量,即:自变量、动态变量、静态变量、模块变量和全局变量。
自变量、动态变量和静态变量只能被定义该变量的表达式所访问;模块变量可被同一模块的所有表达式所访问,其他模块的表达式无法访问(Lu支持模块化编译);全局变量可被所有的表达式所访问。
自变量用于向表达式传递参数,因此自变量也称为形式参数。动态变量只在表达式执行时起作用,一旦表达式执行完毕,动态变量也随之失效。静态变量存在于表达式的整个生命周期,每次表达式执行完毕,静态变量的值被保留。
Lu在编译表达式时,自变量不进行初始化;动态变量初始化为nil;静态变量初始化为0;模块变量和全局变量在第一次生成时初始化为nil,以后使用不再进行初始化。
8 Lu有丰富的运算符和数据类型 [返回页首]
表1:Lu运算符及优先级(仅供了解使用)
运算符类型 |
运算符 | 名称 | 是否允许重载 | 核心库支持的运算 |
说 明 |
双括号连接运算符 | := | 双括号连接 | 冒号前和等号后都必须是括号 | ||
单括号连接运算符 | ( )= | 单括号连接 | 等号后是一个表达式 | ||
[ ]= | 单括号连接 | ||||
{ }= | 单括号连接 | ||||
括号运算符 | ( ) | 小括号 | 括号运算 | 返回最后一个语句的值 | |
[ ] | 中括号 | 括号运算 | |||
{ } | 大括号 | 括号运算 | |||
命名空间成员访问符 | :: | 双冒号 | 访问命名空间成员 | 访问命名空间成员 | |
对象成员运算符 | . | 点 | 访问对象成员或传递函数参数 | 也称为函数参数运算符,或者变量函数调用运算符 | |
后置单目运算符 | ++ | 后置自增 | 是 | 整数、实数 | 后置单目运算符(自增、自减、转置、点转置) |
-- | 后置自减 | 是 | 整数、实数 | ||
' | 转置 | 是 | 未定义 | ||
.' | 点转置 | 是 | 未定义 | ||
前置单目运算符 | ! | 非 | 是 | 逻辑值、整数、实数 |
前置单目运算符(非、正、负、自增、自减、按位非)
对整数或实数求非时,返回逻辑值,且规定!0=true,!0.0=true,其他情况均返回false。 |
+ | 正 | 被忽略 | |||
- | 负 | 是 | 整数、实数、复数、三维向量 | ||
++ | 前置自增 | 是 | 整数、实数 | ||
-- | 前置自减 | 是 | 整数、实数 | ||
!! | 按位非 | 是 | 整数 | ||
乘方算术运算符 | ^ | 乘方 | 是 | 整数、实数、复数 | 算术运算符(乘方、点乘方) |
.^ | 点乘方 | 是 | 未定义 | ||
乘除算术运算符 | * | 乘 | 是 | 整数、实数、复数、三维向量 | 算术运算符(乘、左除、右除、求模、点乘、点左除、点右除) |
/ | 左除 | 是 | 整数、实数、复数 | ||
\ | 右除 | 是 | 未定义 | ||
% | 求模 | 是 | 整数 | ||
.* | 点乘 | 是 | 未定义 | ||
./ | 点左除 | 是 | 未定义 | ||
.\ | 点右除 | 是 | 未定义 | ||
加减算术运算符 | + | 加 | 是 | 整数、实数、复数、三维向量、字符串 | 算术运算符(加、减) |
- | 减 | 是 | 整数、实数、复数、三维向量 | ||
移位运算符 | << | 左移位 | 是 | 整数 | 左移位、右移位 |
>> | 右移位 | 是 | 整数 | ||
关系运算符 | > | 大于 | 是 | 整数、实数 | 关系运算符(大于、大于等于、小于、小于等于、等于、不等于) |
>= | 大于等于 | 是 | 整数、实数 | ||
< | 小于 | 是 | 整数、实数 | ||
<= | 小于等于 | 是 | 整数、实数 | ||
== | 等于 | 是 | 整数、实数、编译符#生成的整数 | ||
!= | 不等于 | 是 | 整数、实数、编译符#生成的整数 | ||
按位与 | && | 按位与 | 是 | 整数 | 按位与 |
按位异或 | ~~ | 按位异或 | 是 | 整数 | 按位异或 |
按位或 | || | 按位或 | 是 | 整数 | 按位或 |
逻辑与 | & | 逻辑与 | 是 | 逻辑值 | 逻辑与 |
逻辑异或 | ~ | 逻辑异或 | 是 | 逻辑值 | 逻辑异或 |
逻辑或 | | | 逻辑或 | 是 | 逻辑值 | 逻辑或 |
并 | $ | 并 | 是 | 整数、实数、复数 | 核心库并运算的结果为复数或三维向量。 |
赋值运算符 | = | 赋值 | 赋值 | 赋值运算符 | |
对象赋值运算符 | .= | 对象赋值 | 对象赋值 | 变量函数调用运算符与赋值运算符的结合,一般用于对象赋值 | |
语句分隔符 | , | 逗号 | 分隔语句 | 逗号、冒号、分号运算符 | |
: | 冒号 | 分隔语句 | |||
; | 分号 | 分隔语句 |
表2:Lu数据类型(仅供了解使用 )
类别 | 基本数据类型 | 标识符 | 例子1 | 例子2 | 例子3 | 说 明 |
静态类型 | nil | nil | nil | 未定义的Lu数据或某个运算失败的返回值。 | ||
表达式(函数)句柄 | @fun | HFor("fun") | 由编译符@或函数HFor获得。 | |||
64位整数 | int | 12 | 0x1A | 0x123D | 64位整数(范围从-9223372036854775808~9223372036854775807),既可以是10进制数,也可以是16进制数,但数字中不能包含小数点,也不能用科学记数法表示数字。16进制整数以0x开头,并用A~F表示10~16。 | |
64位双精度实数 | real | 1.2 | 3. | 10.3E8 | 64位双精度实数(范围大致从±1.7E-308~±1.7E+308),含小数点,可以用科学记数法表示数字。 | |
复数 | complex | 2i | 1+2i | (2$3) | 复数(实部和虚部都是64位双精度实数),以i结尾的数字,或者由运算符$产生。 | |
三维向量 | vector | (1$2$3) | [1$(2$3)] | (2i$3) | 三维向量(三个分量都是64位双精度实数),由运算符$产生。 | |
长精度实数 | 未启用。 | |||||
逻辑值 | true / false | true | false | 2>3 | 逻辑值,只有逻辑真和逻辑假两个值,关系运算或逻辑运算将返回逻辑值。 | |
特殊常量 | all | all | 由系统定义,直接在脚本中使用,其意义由使用这些常量的函数解释。 | |||
data | data | |||||
public | public | |||||
private | private | |||||
protected | protected | |||||
virtual | virtual | |||||
row | row | |||||
rank | rank | |||||
inf / INF | inf | INF | ||||
-inf / -INF | -inf | -INF | ||||
nan / NaN | nan | NaN | ||||
self | self | |||||
method | method | |||||
静态字符串 | "..." | @"..." | @"\[22]" | 静态字符串。 | ||
静态64位一维整数数组 | intss("...") | intss("\&\[10]") | 静态64位一维整数数组。 | |||
静态64位一维实数数组 | realss("...") | realss("\&\[10]") | 静态64位一维实数数组。 | |||
与字符串对应的64位整数 | #abc | #ab_c | 由字符串生成的唯一的64位整数,用于系统扩展设计,用编译符#获得。 | |||
系统定义动态类型 | ||||||
动态64位实数数组 | reals | new[reals,5] | new[reals,2,5] | new[reals,data:2.0,3.6] | 动态64位实数数组。可以是多维数组。 | |
动态64位整数数组 | ints | new[ints,5] | new[ints,2,5] | new[ints,data:2,3] | 动态64位整数数组。可以是多维数组。 | |
动态字符串 | string | new[string,5] | new[string,5,"..."] | new[string,"..."] | 动态字符串。 | |
动态Lu数据 | lu | lu[2,3.5,"..."] | lu{2,lu[3.5,"..."]} | new[lu,5:2,3.5,"..."] | 动态Lu表。可以存放任意类型的数据。 | |
外部扩展动态类型 | 私有动态数据类型 | 由扩展用户提供 | 用户自定义的私有动态数据类型。 | |||
公有动态数据类型 | 由扩展用户提供 | 用户自定义的公有动态数据类型。 |
注:表2中外部扩展动态类型即用户自定义数据类型。
例如你可以设计自定义的矩阵类型并重载+、-、*、/等运算符使之可用于矩阵的运算。Lu的大多数运算符都允许重载。
Lu扩展库LuMath中定义了矩阵类型及相关运算,参考:Lu数值计算扩展动态库LuMath。
10 Lu支持模块化编译,支持对私有数据的保护 [返回页首]
Lu支持表达式(函数)的模块化编译。参考Lu编程指南中的函数LuCom,该函数有一个参数nModule,要求给该表达式指定一个模块号,模块号用整数进行标识。如果用模块加锁函数LockModule对一个模块号进行了加锁,则编译表达式时必须提供加锁函数。
在Lu中,一个模块由一个或多个表达式组成。模块用一个整数标识,整数可正可负,只要绝对值相等,就属于同一个模块。一般用正整数表示该模块名。模块共有两类,即主模块(0#模块)和普通模块(其他标号的模块)。
同一模块中,模块号为负的表达式称私有表达式(私有函数),只能被本模块的表达式所访问(即调用),在其他模块中是不可见的;模块号为正的表达式称公有表达式或全局表达式 (全局函数),能被任何一个表达式所访问。主模块(0#模块)中的表达式都是私有表达式。任何一个表达式,既可以访问本模块中的表达式,也可以访问其他模块中的全局表达式,如果本模块中的一个私有表达式与其他模块的一个全局表达式重名,将优先调用本模块中的私有表达式。
由以上规定可以看出,主模块可以访问本模块中的表达式,也可以访问其他模块中的全局表达式。因此,主模块常常用在Lu脚本的主程序中。
很少有脚本会提供模块化编译功能,但模块化编译的确很有用途,因为一个模块的私有函数和模块变量,除非该模块提供了接口(全局函数),在该模块之外是无法访问的。
实际上,C/C++程序只要获得了表达式的句柄,就可以使用函数LuCal来执行它,无论该表达式是模块私有的,还是全局的。故从C/C++程序来看,对自己编译的Lu表达式,讨论私有或者全局并没有意义。但一个C/C++程序有时并不自己编译Lu脚本(或者只编译部分脚本),例如实用程序OpenLu使用扩展库Mlu编译Lu脚本,这时它只能获得Lu脚本系统中的部分函数(全局函数,或者显示输出的私有函数)句柄,从而使私有数据得到了有效地保护。
11 Lu使用命名空间避免函数重名 [返回页首]
使用命名空间可以有效地避免函数重名问题。Lu中可以用函数Module创建模块命名空间,命名空间创建后,可以用函数OutFun输出该模块的表达式(函数),不管是私有函数还是公有函数,都可以输出。
Module("Name":"Name1","Name2",... ...) //创建模块命名空间Name,继承自"Name1","Name2",... ...
OutFun("fun1","fun2","fun3",... ...) //输出模块命名空间中的表达式"fun1","fun2","fun3",... ...
模块命名空间只能创建一次,可以继承,甚至可以循环继承,如果确实有必要。模块命名空间是一棵树或者是一个连通图。
模块命名空间中输出的表达式可以用命名空间成员访问符::调用,如:Name::fun1(...)。如果该命名空间中没有输出指定的表达式,而该空间的父空间中输出了同名表达式,就会调用父空间中的同名表达式。可以连续使用访问符::直接调用指定父空间(或该父空间的父空间)中的表达式,如:Name1::Name2::Name3::fun1(...)。可以看出,模块命名空间中的表达式调用规则类似于C++中的虚函数调用规则。
为了避免二级函数(使用C/C++设计注册到Lu系统的函数)重名,二级函数也可以采用模块命名空间中的命名方式,如:Fun2::Set(...),称二级函数命名空间。是否采用二级函数命名方式,取决于提供二级函数的模块。
为了避免常量重名,常量也可以采用函数命名空间中的命名方式,如:ConstName::MyConst,称常量命名空间。常量命名空间可由程序或库提供,也可用函数const创建。
由于Lu支持自定义数据类型和运算符重载,故Lu有很强的扩展性;由于Lu支持模块化编译,支持对私有数据的保护,故Lu在扩展时有很强的安全性。
在核心库lu64.dll的支持下,通常通过Lu扩展动态库对Lu系统进行功能扩展,参考:Lu扩展动态库。不过你可以使用Lu核心库的输出函数自己决定扩展方式。
由于Lu支持对私有数据的保护,故不同的人使用不同的语言设计的Lu扩展库会协同工作,而不会相互干扰。
Lu系统中已经实现的常用Lu扩展库见表3。
表3:常用Lu扩展库(仅供了解使用)
Lu 扩 展 库 | 简 介 |
■ Lu系统扩展动态库LuSystem | LuSystem是一个Lu系统扩展动态库,包含一些增强Lu系统功能的函数、对系统内置类型的扩展以及一些新增数据类型等等。LuSystem不仅是对Lu系统的扩充,更在于演示Lu是极易扩充其功能的脚本,很少有脚本允许用户能方便地添加像字典、结构、类等高级的数据结构,但Lu允许,而且实现这些很容易,因而,LuSystem也是编程用户极佳的练手工具。 |
■ Lu数值计算扩展动态库LuMath | LuMath的数值算法是以矩阵为基础,并进行了运算符重载,具有内存消耗低、执行效率高、代码简洁、实用性强的特点。LuMath是熟悉C/C++、Fortran的数学爱好者的极佳的练手工具,任何喜欢LuMath的个人、团队或商业公司可基于此库开发商业程序。 |
■ Lu数值计算扩展动态库LuIMSL | IMSL是一个集合数学与统计函数的链接库,拥有许多精准的数学统计算法,它的强大、可靠的数学与统计链接库能够在执行效率与计算资源间取得极佳的平衡。本库封装了IMSL库的部分实用函数。 |
■ Lu参数优化动态库LuOpt | 优化函数具有极强的全局优化能力,也可用于求解非线性方程(组)。 |
■ Lu窗口库LuWin | 基于Windows API的窗口库,包含一些窗口函数,特别是绘制2D或3D图形的函数,多线程动态绘制图形是LuWin的基本特点。该库需要模块化编译运行库MLu提供支持。 |
■ Lu图形库OpenLuGl | 基于OpenGL的Lu扩展动态库,在独立的线程中动态绘制三维图形。该库需要模块化编译运行库MLu提供支持。 |
13 MLu简化了Lu脚本的使用 [返回页首]
MLu(MLu64.dll)是程序和Lu核心库之间的一个接口库,MLu会自动加载Lu核心库和动态加载多个Lu扩展库,简化了Lu系统的使用;MLu可对Lu源程序进行模块化编译,能够编译运行具有固定格式的源程序(字符串表达式),源程序中可以使用C++风格的注释。此外,MLu还提供了多个线程互斥地访问Lu资源的功能;提供了Lu运行监视器,以退出耗时较长的程序;提供在脚本中动态编译函数的功能;提供错误处理函数,实现错误处理的恢复模型等等。
下例是MLu源代码的格式(仅作举例,不理解没关系):
/**********
八皇后问题是一个古老而著名的问题,是回溯算法的典型例题。
该问题是19世纪著名的数学家高斯1850年提出:在8×8格的国际象棋盘上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。
以下算法是从网上搜来的,该算法没有最终给出排列组合,仅仅给出有多少种组合,但是算法确实十分奥妙。
***********/
//Lu源程序
init(::sum,upperlim)= sum=0, upperlim=1, SetStackMax(1000); //执行init函数进行初始化
test(row, ld, rd : pos,p : sum,upperlim)= //函数定义
{
which //which是一个选择计算函数
{
row != upperlim,
{
pos = {upperlim && [!!(row||ld||rd)]},
while{ pos, //while是循环函数
p = pos&&(-pos),
pos = pos -p,
test[row+p, (ld+p)<<1, (rd+p)>>1]
}
},
sum++
}
};
main(:tm,n:sum,upperlim)= //执行main函数获得结果
{
tm=clock(), n=13,
upperlim=(upperlim<<n)-1,
test(0,0,0),
o["Queens=",n,",sum=",sum,",耗时约",[clock()-tm]/1000.0,"秒。\r\n"]
};
参考:Lu模块化编译运行库MLu。
14 Lu提供自动内存管理,也可以手动管理内存 [返回页首]
C程序员要自己管理内存的分配和回收,而Python具有垃圾自动回收的机制,Lu的动态内存管理兼有二者的特点:既可以手动回收垃圾,也可以完全依赖于Lu的垃圾自动回收机制。通常,Lu中用类似new的函数生成动态对象,而用类似delete的函数销毁动态对象,这一点类似于C,用户可以高效地管理内存;所有用户没有销毁的对象,会由Lu的垃圾收集器管理,并最终会被Lu安全地回收,这一点类似于Python。
Lu的内存管理特点:(1)与C/C++类似,用户可立即销毁一个对象;(2)被用户忽略的垃圾将被自动回收;(3)任何时候,可手动立即启动垃圾收集器;(4)垃圾回收是有运行开销的,但如果用户有效地管理了内存,垃圾回收器可以一次也不启动。
15 Lu混合编程中对象操作特点 [返回页首]
混合编程的关键是参数传递。Lu是一种嵌入式脚本,采用自动垃圾回收与手动垃圾回收并存可在混合编程中简化脚本使用、扩大脚本使用范围并提高混合编程效率和运行效率。
设主程序语言为C/C++或delphi等,主程序中有一个对象(或结构等)A,要实现在主程序和Lu脚本中对A的联合操作。
首先,要使主程序和Lu都能操作对象A,对象A必须注册到Lu系统中,可注册为两类对象,一种注册对象可被垃圾收集器回收,另一类注册对象垃圾收集器无法回收。此外,还要向Lu注册一些操作对象A的函数。
有以下多种联合操作方式:
(1)注册为垃圾收集器无法回收的对象,基本特点为:
主程序可生成对象A并注册到Lu系统,对象A也可在脚本中由专用函数生成;
主程序可销毁对象A,Lu脚本中也可销毁对象A;
主程序或脚本中都可一次销毁对象A的所有实例;
主程序或Lu脚本用户没有销毁的实例由Lu系统最终回收。
(2)注册为垃圾收集器可回收的对象,基本特点为:
主程序可生成对象A并注册到Lu系统,对象A也可在脚本中由专用函数生成;
主程序可销毁对象A,Lu脚本中也可销毁对象A,销毁可以是立即进行的,或者暂存到缓冲池中;
主程序或脚本中都可一次销毁对象A的所有实例;
主程序或Lu脚本用户没有销毁的实例由Lu系统最终回收。
主程序可按一定规则启动垃圾收集器回收垃圾对象;
Lu脚本中可立即启动垃圾收集器回收垃圾对象;
主程序可设置垃圾收集器不能启动,则脚本中的垃圾收集器也无法运行。
注:Lu垃圾收集器采用标记清除算法。
(3)多种对象并存时,有些对象注册为垃圾收集器可回收的对象,有些对象注册为垃圾收集器不可回收的对象,各自具备各自的特点,不相互影响。
由于自动垃圾回收与手动垃圾回收并存,故无论在主程序,还是在Lu脚本中销毁一个对象,不必担心会带来任何问题。而只采用自动垃圾回收的脚本系统,在实现复杂功能时,主程序和脚本系统接口上需费很多心思,往往会费力不讨好。
虽然许多脚本支持协程,但Lu脚本协程更简单,效率更高。
如果表达式(函数)中使用了函数yield,该表达式称为一个协程(coroutine)。协程不能递归运行,只有这一个限制。Lu协程有4种状态:正常、运行、挂起、 终止。正常态是可以运行但还没有运行的状态;终止态协程是不能运行的,如果运行将返回nil。与协程相关函数有5个:
yield:挂起协程并立即返回表达式(函数)的值。
status:查询表达式(包含协程)的状态。
abort:中止挂起的协程,此时协程处于正常态。
terminate:终止协程,协程处于终止态,不能运行。
resume:重启一个终止的协程,协程转为正常态。
例子(MLu代码):
f(x:i)= i=0, while{(i++, i<=5), yield(i)}, 888; //定义了协程f
f[0]; f[0]; f[0]; f[0]; f[0]; f[0]; f[0]; f[0]; //多次调用协程f
结果(返回888时协程转为了正常态):
1
2
3
4
5
888
1
2
Lu是动态强类型的,是指Lu在运行时进行类型检查(动态),且进行严格的类型检查(强类型)。例如函数f:
f(x,y)=x+y
执行f(1,2)会得到3,执行f("ab","cd")会得到"abcd",但执行f(1,"cd")会出现运行错误(除非定义了整数和字符串相加的运算,否则将出现运行错误)。
由于Lu是强类型的,故Lu脚本中5和5.0是不一样的,5是一个整数,而5.0是一个实数。所以在Lu中,11/5=2,而11/5.0=2.2(进行了隐式转换,11被自动转换为了11.0)。
Lu的强类型检查,配合Lu的自定义数据类型和运算符重载,可实现C/C++中的单字节字符类型char,参考使用C/C++给Lu静态类型数据添加运算符重载功能;也可以实现自定义对象三维向量及相关运算,参考C/C++注册动态对象到Lu系统并进行运算符重载。
Lu使用Unicode字符串作为默认字符串,可很好地实现中文编程。Lu标识符可全部使用中文。
例子:
两数加(加数1,加数2)=加数1+加数2;
两数加(2,3);
Lu是由C实现的,故是可移植的,但目前仅提供了在windows系统中的版本lu64.dll。
版权所有© Lu程序设计
2011-2021,保留所有权利
E-mail: forcal@sina.com
QQ:630715621
最近更新:
2021年06月30日