如梦令编程语言发布 (RML)

如梦令编程语言是在Rebol语言核心语法的基础上,做了一些自以为是的修改而来。谨以此为Rebol语法的传承,略尽绵薄之力。

基本概念

如梦令语言分属Lisp语系,代码本身是一个层层嵌套的Token列表,代码与数据具有同像性,与目前流行的C系编程语言有较大区别。RML的代码在运行时分割为Token列表,每个Token通过其字面表示的格式确定类型。 主流的编程语言通常会定义一系列的语法规则来实现程序所需的各种功能,而RML中只有一种核心语法:表达式的长度和实现的功能由头部Token确定,当获取到的Token数量满足头部Token的要求时,判断表达式完整,并进行求值。其与传统Lisp语言的区别在于,Lisp中表达式的长度依靠括号()来确定,因此Lisp往往被吐槽括号太多,影响阅读。RML中剔除了这一依赖,便于书写,另一方面也带来了表达式定长的限制,通过修饰字的概念,能够减少这种限制带来的不便,这便是RML在语法上的取舍。

基本语法

第一行代码

print "hello word"

注释

;这是单行注释

数据类型

n    i:   123    4.56    true    "hello"    #'A'   [1 2 3]    (1 2 3)    {a: 123}    a/b/c   %rml/go/rml.go  #{0a0b} 

Rebol中提供了多达50种数据类型,RML目前实现了常用的一些基本数据类型,从左到右分别是 单字设字整数小数逻辑字符串字符方块圆块对象路径文件二元 类型,数据类型有对应的字面表达格式,主要通过空白字符分隔。集合类型首先被视为单个Token,内部另行分割。

赋值

i: 123    j: 456
x: j: 789

取值

i       ;输出123

中缀运算

1 + 2 * 3     	;输出9
1 + (2 * 3)   	;输出7

传统Lisp语言不支持中缀运算符,RML中为了贴近使用习惯,提供了中缀运算支持。中缀运算优先级比一般表达式高,但中缀运算符间优先级相同。

路径类型

路径类型用于集合类型的存取操作,形式上是一串连续的以 / 连接的Token,以此表示层级关系,例如 a/b/c/1
路径中可以插入圆块和取字进行动态求值,例如

b/(1 + 2)/a         ;等同于b/3/a

方块类型

方块类型 [] 等同于Lisp中的列表,类似于其他语言中的Array/List的概念,通过路径类型可以对方块进行设值、取值操作。

blk: [1 2 3]
blk/2                   ;输出2
blk/2: 5
blk                     ;输出[1 5 3]

方块主要通过序号作为索引,且序号从1开始。

对象类型

RML中的对象对应了Rebol中语境的概念,其本质是一个具有层级关系的 map,每个对象都存放了其父级对象的指针。与Rebol不同,RML中对象的字面格式类似于 js

obj: {a: 123 b: 456 c: {d: 789}}

对象类型支持嵌套,同样通过路径进行操作

obj/c/d         ;输出789
obj/c/d: 987
obj/c/d         ;输出987

自定义函数

f: func [n] [n * 2]
f 2         ;输出4

通过内置的原生函数 func 可以实现用户自定义函数。 func 需要两个参数,第一个是参数列表的方块,第二个是要执行的代码方块。函数会返回最后一个表达式的返回值,也可以通过 return 来手动返回值。

循环

loop 3 [print "hello"]

repeat i 3 [print i]

for i 1 3 1 [print i]

while [i < 5] [print i]

分支

if 1 > 2 [print 1]                  ;跳过
either 1 > 2 [print 1] [print 2]    ;打印2

多线程

fork [fib 40]                   ;启动一个Goroutine进行计算,不等待
res: 0
fork/result [fib 40] res        ;通过修饰字,指定分支线程返回值的接收者

spawn [ [print fib 40] [print fib 40] ]             ;启动两个Goroutine进行计算,不等待
spawn/wait [ [print fib 40] [print fib 40] ]        ;启动两个Goroutine进行计算,并等待其全部执行完毕

中文支持

打印 "你好,世界"           ;中文版hello world


;下面是求10000以内素数的中文代码
集合为 []
	
历 甲 1 10000 1 [
    是素数为 真
    历 乙 2 (甲 除以 2) 1 [
        若 甲 模 乙 等于 0 [是素数为 假 跳出]
    ]
    若 是素数 [
        添加* 集合 甲
    ]
]

打印 集合

即时帮助

RML的内置函数都定义在最底层的lib语境中,可以通过以下方式查看lib语境中的定义

lib?        ;中文为  库?

RML支持在定义函数时添加关于函数和参数的描述,并可以在解释器中查看这些帮助信息。目前RML中初始化定义的中文函数都添加了相关的帮助信息,查看方式如下:

帮助 写出       ;英文对应  help write   或  ? write

;输出的帮助信息
FUNC:
  desc:    将数据写出到文件中

  args:    路径         要写出数据的文件
           数据         要写出的数据,接受字符串和二元类型

  props:   /添加        无参,在文件的结尾添加数据而不是覆盖

性能

目前RML语言的性能很差。用于采用了逐字解释和动态作用域,整体性能相对主流语言有较大差距。尤其是在深层次递归函数运算中,由于语境的堆叠,影响了取值操作的性能。一定时期内,性能问题都不是RML主要考虑的问题。对计算性能有较高要求的部分,RML可以通过宿主语言定义原生函数,从而实现宿主语言的性能。例如求斐波那契数列,用RML实现 fib 30 在E5-1620CPU上大约耗时8秒,而通过在go中定义,在RML中调用的方式,则只需6毫秒,性能提高上千倍。

语言谱系

RML分属Lisp语系,对,就是那个一边被认为高逼格,同时又被疯狂吐槽括号太多的语言。从语言发展的历史来看,Lisp和C分别代表了编程语言的两个极点。C语言是贴近硬件和高性能的典范,而Lisp则是高度抽象的代表。虽然Lisp语言日渐式微,但由其首创的许多特性如 GC 在当今主流语言中得到了延续。
RML直接继承自Rebol语言。Rebol语言由Carl Sassenrath于1997年发布问世,并进行了持续数年的商业化运作,但最终没能获取商业上的成功。Carl是世界上第一个提供真彩色的操作系统AmigaOS的架构师,其编程功力可见一斑。

与Rebol的区别

  • 引入语境类型的概念,增强对语境的操作
  • 取消间接值的概念,复杂数据类型字面值解析前后一致
  • Rebol不支持多线程,RML提供多线程并行功能
  • RML采用动态作用域,性能较Rebol差

相关链接

github

D语言版本实现分析

你可能感兴趣的:(如梦令编程语言发布 (RML))