4. 定义 SLang 2¶
4.1. SLang 2:一种命令式语言¶
现在,我们将向这门简单语言加入一些超出纯函数式编程范畴的特性。
在这个新版本的 SLang 中,即 SLang 2 (Simple Language version 2),标准算术运算符和布尔运算符现在采用中缀形式,这只是具体语法 上的一点小改动。更重要的是,我们新增了 if-then-else 表达式, 以及赋值语句、打印语句,还有 let 块内语句的顺序执行。这最后三项 新增内容(即语句的新增,而非表达式的新增)合在一起,把我们的简单 语言变成了一种 命令式语言 ,也就是说,程序员依靠改变变量状态 (即副作用)来计算所需的值。
向 SLang 添加赋值语句
语法:
<exp> ::= <var_exp> | ... | <assign_exp>
...
<assign_exp> ::= set <var_exp> = <exp>
语义:
求值等号右侧的表达式(即 RHS 表达式)。
把所得的值赋给左侧的变量(即 LHS)。
返回 RHS 表达式的值。
表达式在求值时返回值。语句在求值时产生副作用。
赋值语句实际上是一种 表达式语句 ,因为它既是表达式(因为它 返回一个值),又是语句(因为它有副作用)。
向 SLang 添加打印语句
语法:
<exp> ::= <var_exp> | ... | <print_exp>
...
<print_exp> ::= print <exp>
语义:
求值该表达式。
把所得的值发送到控制台。
不返回任何值(即 JavaScript 中的 ‘undefined’)。
这是一种 纯语句 ,即没有返回值的语句。
向 SLang 的 let 块添加顺序执行
语法:
<exp> ::= <var_exp> | ... | <let_exp>
<let_exp> ::= let <bindings> in <block> end
...
<block> ::= <exp> ( ; <exp> )*
注意,分号是表达式分隔符,而不是终止符。
块的语义:
按顺序求值块中的表达式。
返回最后一个表达式的值。
为了让顺序执行有用,块中的所有表达式(最后一个除外)必须是 什么?
示例: 利用上面关于赋值、打印和顺序执行的语义定义,说服自己 相信下面的示例程序会产生右侧所示的输出。做完之后,再通过尝试 这个随机化问题来获得更多练习。
let Output:
x = 1
y = 2
sqr = fn (x) => (x * x)
in ["Num",6]
let ["Num",2]
f = fn (x) => (y * x) ["Num",64]
g = fn () => set y = add1(y) ["Num",10]
h = fn () => set x = add1(x) ["Num",6]
x = 3 ["Num",15]
in ["Num",50]
set x = (2 * x);
print x; print y;
print (sqr (x + y));
print (f 5);
(g);
(h);
print x;
print (f 5);
set y = 10;
print (f 5)
end
end
4.2. SLang 2 程序的输出¶
下面的问题将帮助你掌握 SLang 2 的语法和语义。要获得这道题的学分, 你必须连续三次正确完成这个随机化问题。
提交答案时,请记住给出完整的指称值,例如 [ "Num", 0 ] ,而 不只是 0 。
