这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战」
S-Expressions
S-expression(或者为 "symbolic expressions")由McCarthy在他的LISP编程语言的论文上提及。最初是作为一种程序员不能操纵的中间表达形式。下面是几个S-expression的例子:
(if x y z)
(* (+ 2 6 4) 3)
(define (f x) (if (= x 0) 1 (* x (f (- x 1)))))
s-expression 是一种非常简单可以表示结构化的表达式。由于其便利性,经常在编译器或者解释器中用到。上面的三个s-expression例子可以归纳成:
- Symbols: 例如
f和if - Numbers
- Lists: S-expression中的序列用小括号括起来,像
(+ 2 6 4)和(* (+ 2 6 4) 3)
OCaml 中的S-expression
如何在OCaml中表示S-expression。一种选择是使用字符串
let e1 = "(if x y z)"
let e2 = "(* (+ 2 6 4) 3)"
但是,用这种方式使用起来会很麻烦。我们可以在OCaml中添加一个新的类型来表示S-expression
utop # type s_exp =
Sym of string | Num of int | Lst of s_exp list;;
其中, Sym、Num和Lst为构造器:用来构造S-expression。构造器后面的of代表这个数据对应的类型。例如,符号if为s_exp中的Sym, 以此类推。Lst用来定义表达式是递归的。
这样, (if x y z)就会表达成
let e1 = Lst [ Sym "if"; Sym "x"; Sym "y"; Sym "z"]
( * ( + 2 6 4 ) 3 )就会表达成
let e2 = Lst [Sym "*"; Lst [Sym "+"; Num 2; Num 6; Num 4]; Num 3]
与字符串表达式相比,这种表示方式显得更加臃肿,但是这种表示方式暗含了s-expression的递归的结构。我们也可以用模式匹配,来进行构造s-expression
utop # let which_construtor (e : s_exp) : string =
match e with
| Sym x -> "a symbol"
| Num n -> "a number"
| List l -> "a list";;
例如:
let rec total (e: s_exp) : int =
match e with
| Sym _ -> 0
| Num n -> n
| Lst l -> List.fold_left ( + ) 0 (List.map total l)
可以思考一下如何在编译器中,实现条件判断
在Javascript 中,条件语句
if(x) {
return y;
} else {
return z;
}
在Python中 条件语句
if x:
return y
else:
return z