90分钟实现一门编程语言(极简解释器教程)

2019-12-30 14:54:22王冬梅

定义变量

iScheme使用`def`关键字定义变量


>> (def a 3)
>> 3
>> a
>> 3

算术|逻辑|比较操作

与常见的编程语言(C#, Java, C++, C)不同,Scheme 使用 波兰表达式,即前缀表示法。例如:

C#中的算术|逻辑|比较操作


// Arithmetic ops
a + b * c
a / (b + c + d)
// Logical ops
(cond1 && cond2) || cond3
// Comparing ops
a == b
1 < a && a < 3

对应的iScheme代码


; Arithmetic ops
(+ a (* b c))
(/ a (+ b c d))
; Logical ops
(or (and cond1 cond2) cond3)
; Comparing ops
(= a b)
(< 1 a 3)

需要注意的几点:

iScheme 中的操作符可以接受不止两个参数——这在一定程度上控制了括号的数量。
iScheme 逻辑操作使用 and , or 和 not 代替了常见的 && , || 和 ! ——这在一定程度上增强了程序的可读性。
顺序语句

iScheme使用 begin 关键字标识顺序语句,并以最后一条语句的值作为返回结果。以求两个数的平均值为例:

C#的顺序语句


int a = 3;
int b = 5;
int c = (a + b) / 2;

iScheme的顺序语句


(def c (begin
  (def a 3)
  (def b 5)
  (/ (+ a b) 2)))

控制流操作

iScheme 中的控制流操作只包含 if 。

if语句示例


>> (define a (if (> 3 2) 1 2))
>> 1
>> a
>> 1

列表类型

iScheme 使用 list 关键字定义列表,并提供 first 关键字获取列表的第一个元素;提供 rest 关键字获取列表除第一个元素外的元素。

iScheme的列表示例


>> (define alist (list 1 2 3 4))
>> (list 1 2 3 4)
>> (first alist)
>> 1
>> (rest alist)
>> (2 3 4)

定义函数

iScheme 使用 func 关键字定义函数:

iScheme的函数定义


(def square (func (x) (* x x)))
(def sum_square (func (a b) (+ (square a) (square b))))

对应的C#代码


public static int Square (int x) {
  return x * x;
}
public static int SumSquare(int a, int b) {
  return Square(a) + Square(b);
}

递归

由于 iScheme 中没有 for 或 while 这种命令式语言(Imperative Programming Language)的循环结构,递归成了重复操作的唯一选择。

以计算最大公约数为例:

iScheme计算最大公约数


(def gcd (func (a b)
  (if (= b 0)
    a
    (func (b (% a b))))))

对应的C#代码


public static int GCD (int a, int b) {
  if (b == 0) {
    return a;
  } else {
    return GCD(b, a % b);
  }
}