NLang0.9.0发布了。连同此前的0.8.1到0.8.5,这一轮迭代的主要内容:让NLang从「自己跑得很好的脚本语言」,变成「能住进C++程序里的脚本语言」。0.9.0删掉了new关键字、收紧了命名规则;0.8.2提供了进程内嵌入API;0.8.5补全了异常边界;其余版本专心补语法、磨开发体验。下面按主题过一遍。
对象创建不再需要new(v0.9.0)
NLang的类实例全部由垃圾回收器统一管理,创建对象时根本不存在「该用哪种分配方式」的选择题。new既不带类型信息,也不改变语义,语言里没有任何场合需要靠它区分「创建」和「调用」------它存在的全部意义,就是让你多敲四个键。Swift、Go、Kotlin、Python早都做过同样的取舍,NLang这次算从善如流。
删掉new之后,它恢复为普通标识符,对象创建由一组更直接的语法承担,其中几项是旧版本没有的能力:
- 构造调用 :
Point(2, 3)可出现在任何表达式位置,跨模块写作shapes.Point(2, 3); - 直接初始化声明 :
Pointp(2, 3);,声明即构造,沿用C++的写法; - 花括号初始化 :
Point{x: 2, y: 3},没有构造器的类和结构体,在类型名后按字段名直接组装; - 数组创建表达式 :
int[3]、Foo[n],长度可以是运行期的值; - 定长数组声明 :
int a[3];元素初始化为零,strings[n];接受运行期长度,intb[100]=[7, 8];支持部分初始化------前两个有值,剩下98个老老实实归零; - 按目标类型推断的字面量 :
int[] a = {1, 2};、List<int> l = [3, 4];、Dict<string,int> d= {"a": 5};,方括号与花括号的书写形状配合目标类型共同决定容器种类,空容器统一写作{}`。
旧写法不会降级成警告,直接编译报错,没有过渡期。
变量名不得复用类型名(v0.9.0)
这个限制的动机很务实:此类声明此前能通过名称解析,但后续行为全凭运气------轻则报出八竿子打不着的编译错误,重则编译通过后在运行期崩溃。
运行错误可捕获、可定位(v0.8.5)
以前as向下转型失败,表现为虚拟机内部错误,NLang层面的try/catch只能干瞪眼。0.8.5把它改成抛出内建的InvalidCastException:可以被捕获,message字段可读,也可以主动构造后抛出------当然,按0.9.0的规矩,构造它不需要new。类型转换失败从此进入正常的异常处理流程。
定位错误也更直接。nide终端输出里的(file:line)引用支持Ctrl+单击跳转到源码;新增的「运行错误」页签列出本次运行的全部错误与回溯行,双击即可跳转。回溯信息本身也做了修正:每一帧携带真实的编译期源文件路径,多文件项目终于不用每一帧都看着同一个文件名发懵;未捕获的用户throw在顶层报告异常自身的消息,而不是固定的userthrow文本。
另外,ncc --no-debug-info可以剥离逐语句调试信息以缩小产物体积,代价是回溯行号显示为(file: ?)、断点与单步不可用------适合发布构建,也适合一切不想让人看清行号的场合。
下标复合赋值(v0.8.4)
arr[i]+=v这类以下标为左值的复合赋值在0.8.4补齐。数组、List、Dict三种容器均支持+=、-=、*=、/=、%=五种运算;成员作为基址(h.a[i] += v)与嵌套下标(m[i][j] += v)同样可用,基址与下标保证只求值一次;for的更新子句也接受i += 1这样的写法。
这个版本还修复了一个Release构建下的编译器崩溃:对内建方法的返回值继续链式调用,比如a.length().toString(),会让ncc当场去世。
语言细节规范化(v0.8.3)
两处写法做了统一。
数组长度从属性改为方法:写作arr.length(),与string.length()及内建容器一致;属性形式arr.length是编译错误,没有适应期。
函数类型改用小写关键字func:唯一写法是func<Return, Params...>,旧的Func<...>拼法报编译错误,Func恢复为普通标识符;List、Dict保持大写类名不变。
C++嵌入API(v0.8.2)
这是本轮「可嵌入语言」的基础设施。nlang::Interpreter允许宿主程序在进程内加载并运行编译好的.ncu/.npkg产物;可以注册宿主函数供脚本回调;通过类型化的值与容器代理读写数据(代理持有期间,对象在垃圾回收根集合中得到保证,不会被半路收走);脚本中未捕获的异常会转换为C++异常抛出;脚本输出也可以整体重定向。用户手册新增「Embedding NLang」一章,examples/embed_host是最小可用的宿主示例------照着抄就能跑起来。
获取与更新
版本下载:github.com/dliting/nlang/releases
0.8.1到0.8.5的各版本同样在releases页面。
总结
从0.8.1到0.9.0,NLang的迭代始终围着同一条主线转:创建语法更轻、命名规则更严、异常边界更完整、宿主接口就位。语言的定位没有变化------面向嵌入与自动化场景的静态类型脚本语言;变化在于,支撑这一定位的地基,在这几个版本里一块一块铺齐了。