w3ctech

[ReasonML] - let bindings and scopes - let绑定与作用域


原文:http://2ality.com/2017/12/let-scopes-reasonml.html

翻译:ppp

系列文章目录详见: “什么是ReasonML?


本文中,我们将了解在ReasonML中如何变量的定义以及变量的作用域。

1. 简单 let 绑定

定义变量如下:

# let x = 123;
let x: int = 123;
# x;
- : int = 123

以这种方式绑定(变量-值)的变量都是不可修改的-你不能再为该变量赋其他的值。这样的规范是为了使值也是不可变的,但我认为也不是非得如此。

由于这种变量与值得绑定是不可变的,所以必须在定义时立即初始化变量。你不能定义一个没有初始化的变量。

2. 变量的重定义

ReasonML允许你重新定义变量:

# let x = 1;
let x: int = 1;
# x;
- : int = 1
# let x = 2;
let x: int = 2;
# x;
- : int = 2

这与绑定后不可修改的特性相并不冲突:它更像是嵌套了作用域,而不是更改变量的值。

能够重新定义变量这一点在命令行中特别有用。

3. 指定类型

支持显示的为一个变量指定类型:

# let y: string = "abc";
let y: string = "abc";

对于复杂的类型,显示声明有时是需要的,但是对于简单类型而言,显得有些多余。

4. 通过作用域块创建新的作用域

变量的作用域作为一种语法结构,定义了变量的存在范围。块让你能够引入新的作用域,以花括号{}开始和结束:

let x = "hello";
print_string(x); /* hello */
{ /* A */
    let x = "tmp";
    print_string(x); /* tmp */
};  /* B */
print_string(x); /* hello */

代码中的块由A行开始,B行结束。

这个块的内部有和他上层一样的结构。

为什么在B行结尾的花括号后面有一个分号呢?因为块本身也是另一个表达式。它的值等于它内部最后一个表达式的值。这意味着你可以把代码块放在任何可以放置表达式的地方:

let x = { print_string("hi"); 123 }; /* hi */
print_int(x); /* 123 */

另一个例子:

print_string({
    let s = "ma";
    s ++ s;
}); /* mama */

这里祭出在ReasonML中一个核心也是基本思想:一切皆表达式。

w3ctech微信

扫码关注w3ctech微信公众号

共收到0条回复