用JavaScript实现一门编程语言 2 (λanguage语言简介)

119 阅读3分钟

译者:miaoYu

原文链接

在开始之前,应该对我们要是现实什么有清晰的认识。

我们新语言(λanguage)的大概语法如下:

# 这是注释

println(""Hello World!"");

println(2 + 3 * 4);

# `lambda` 或者 `λ`可以定义函数
fib = lambda (n) if n < 2 then n else fib(n - 1) + fib(n - 2);

println(fib(15));

print-range = λ(a, b)             # `λ``lambda` 功能相同
                if a <= b then {  # `then` 关键字是可省略的(看下面)
                  print(a);
                  if a + 1 <= b {
                    print("", "");
                    print-range(a + 1, b);
                  } else println("""");
                };
print-range(1, 5);

注意上面的标识符(print-range)可以包含减号。从个人喜好来讲:我喜欢用空格把运算符隔开。我不喜欢驼峰命名法,比起下划线我更喜欢用横杠。所以说自己创造语言最爽的就是可以完全按照自己的喜好来设计。:)

控制台输出:

Hello World!
14
610
1, 2, 3, 4, 5

λanguage看起来有点像JavaScript,但其实并不是。首先,没有申明,只有表达式。一个表达式返回一个值也可以替换其他表达式。分号用来间隔表达式。花括号用来创建表达式序列,并且它本身也是一个表达式。如下:

a = {
  fib(10);  # 没有副作用, 但总会执行
  fib(15)   # 最后一个分号可以省略
};
print(a); # 打印出 610

函数被lambda 或者 λ 关键字定义,两个关键字作用一样。关键字后面必须跟上括弧,括号里变量名用逗号分隔,和JavaScript类似。函数体是一个单一的表达式,也可以是包裹在{...}中的序列。最后一个表达式的计算得到的值会被返回。

这里没有var来创建新的变量,你可以用IIFE(立即执行函数表达式),用一个lambda,声明变量作为参数。变量拥有函数作用域,函数是闭包 — 和JavaScript一样。

尽管if它本身就是一个表达式。也可以得到和JavaScript三元运算符类似的效果。

a = foo() ? bar() : baz();           // JavaScript
a = if foo() then bar() else baz();  # λanguage

当分支通过花括号({)开始,那个then关键字是可以省略的(你可以看上面print-range的例子),其他情况then就不能省略了。else关键字用来创造分支。thenelse作为一个单一表达式,当然你也可以通过花括号和分号组合多个表达式。

λanguage中false是关键词,也是唯一表示错误的值:

if foo() then print(""OK"");

如果foo() 的返回值不是false,将打印出""OK""。当然也有一个true关键词表示完成,所有不等于false的都是true(包括数字0和空字符串"""")。

上面还有需要注意的就是,if条件语句不需要括号,当然加了也不会报错。

一个完整的程序被编译,就像嵌入在大括号里一样,因此你需要在每个表达式后面加分号,最后一个表达式除外。


这就是我们小巧的λanguage,它未必是一个好的语言,它有它的缺陷。有很多特性缺失,比如对象、数组;我们不会把经历放在这些上面,因为它们对于接下来的旅程没有什么帮助。如果这些都搞懂了,那么你也可以很轻松的实现所有的特性。

在下个章节我们将开始写λanguage的解析器了。