Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

如何用JavaScript实现一门编程语言 - λanguage描述 #8

Open
llwanghong opened this issue Apr 28, 2023 · 0 comments
Open

如何用JavaScript实现一门编程语言 - λanguage描述 #8

llwanghong opened this issue Apr 28, 2023 · 0 comments

Comments

@llwanghong
Copy link
Owner

llwanghong commented Apr 28, 2023

整篇译文的目录章节如下:

整篇译文的目录章节如下:

λanguage描述

一切开始之前,我们应该对要取得的目标有一个清晰的认识。使用严格的语法来描述λanguage语言不失为一个好想法,但本教程中,我尽量保证描述更通俗,比如下面的示例:

# this is a comment

println("Hello World!");

println(2 + 3 * 4);

# functions are introduced with `lambda` or `λ`
fib = lambda (n) if n < 2 then n else fib(n - 1) + fib(n - 2);

println(fib(15));

print-range = λ(a, b)             # `λ` is synonym to `lambda`
                if a <= b then {  # `then` here is optional as you can see below
                  print(a);
                  if a + 1 <= b {
                    print(", ");
                    print-range(a + 1, b);
                  } else println("");        # newline
                };
print-range(1, 5);

注意上面标识符名称(print-range)可以包含减号"-"。这纯属个人的喜好:我总是喜欢在操作符前后加上空格,不是特别喜欢驼峰命名,并且短中划线比下划线要更好点。创造自己的编程语言的好处就是可以按照自己的喜好来实现。:)

输出如下:

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

λanguage语言虽然看起来有点像JavaScript,但是它们不一样。首先,λanguage中只有表达式而没有语句。一个表达式会返回一个值并且可以用来代替任何其它表达式。花括号“{}”用来创建一个表达式序列,其中用分号“;”来分割各个表达式,表达式序列本身也是表达式,它的值是最后一个表达式的值。下面是一个有效的程序:

a = {
  fib(10);  # has no side-effects, but it's computed anyway
  fib(15)   # the last semicolon can be missing
};
print(a); # prints 610

通过关键字lambda或者λ(两者是同义词)引入函数。紧跟着关键字后面必须是由圆括号()包裹且由逗号,分隔的变量列表(也可以为空),像JavaScript一样,这些变量就是函数参数名称。函数体是一个单一的表达式,也可以是一个由“{}”包裹的表达式序列。没有return语句(因为λanguage不支持语句),所以函数体中最后一个表达式的值会被返回给调用者(caller)。

没有var关键字。可以使用JavaScript程序员所谓的“IIFE”来引入新变量。使用lambda将变量声明为参数。跟JavaScript一样,在λanguage语言中,变量同样拥有函数作用域,函数都是闭包。

甚至if关键字本身就是一个表达式。在JavaScript中需要使用三目运算符达到下面的效果:

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

上面print-range代码片段可以看到,当分支是以左花括号{开始的时候,then关键字可以省略,否则是必需的。如果有选择分支的话,则else关键字是必需的。与函数体类似,thenelse关键字的分支体也是一个单一的表达式,同样可以是一个由花括号{}包裹的,且分号;分割的表达式序列。当条件为false并且没有选择分支的时候,if表达式的值为false。说到这,false是λanguage语言中代表假值(falsy value)的唯一一个关键字:

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

上面的代码当且仅foo()的值不为false时才会打印OK。考虑到语言的完整性,也有一个true关键字,任何不为false(按照JavaScript的===操作符判断)的条件(包括数字0和空字符串“”)都会被解析为true。

另外需要注意的是,if的条件不要求必须用圆括号包裹。虽然加上了也不会错(左圆括号(代表一个表达式的开始),但总有些多余。

整个程序会假定被包裹在花括号{}中来解析,所以需要在每个表达式后面加上分号;(最后一个表达式可以除外)。

好了,上面就是我们的λanguage语言。它不一定算是一个好编程语言。语法看起来很小巧,但是会有缺陷。有许多缺失的特性,比如对象或数组,我们不会投入过多精力在上面,因为它们不是必须的。如果能够理解本教程所有的内容,你可以轻易的实现这些特性。

下一节我们将要来写一个λanguage语言的解析器。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant