w3ctech

[ReasonML] - Basic values and types - 基础的值与类型


原文:http://2ality.com/2017/12/basic-types-reasonml.html

翻译:ppp

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


本文中,我们将看看ReasonML对布尔值,整数,浮点数,字符串,字符和单元类型的支持。同时还有一些运算符的用法。 为了进一步学习,我们将使用ReasonML的交互式命令行rtop,它是reason-cli工具包的一部分(安装手册)(译者注:发展太快,现在这个工具很难找到了,官方推荐用在线的运行环境来测试,也很方便地址)。

1. rtop 中的交互

rtop 的交互如下。

# !true;
- : bool = false

有两点值得注意: 为了得到一个表达式的值,你需要用;分号来结束它,例中的!true;。 rtop 通常会打印出运算结果的类型。这一点将会在处理像函数这样更为复杂的类型时,变得非常有用。

2. 如何理解 ReasonML 是静态类型的语言?

ReasonML中的值是静态类型的。 什么是静态类型? 首先,类型就是一组值的集合。 例如,bool是所有布尔值类型的集合: {false, true}的集合。 其次,我们再对代码生命周期的上下文做出以下区分:

  • 静态:在编译时,即不运行代码。
  • 动态:在运行时,即代码正在运行。

因此,静态类型意味着:ReasonML在编译时就知道值的类型。而且在编辑代码时也会知道,这将支持更智能的编辑。

2.1 接受静态“类型”

我们已经知道了静态类型的一个好处:在编辑时对类型已知。这能帮助我们检测一些类型错误,同时还有助于做一些代码逻辑上的检查。(译者注:相对于JavaScript的动态类型而言) 为了上述的好处,你应该接受静态“类型”。有两种方式可以帮助你: ReasonML会智能的推断出类型(尽管你可能没有显示的指定)。这种被动式的类型预测让你用起来更方便顺手。 在出现问题时,ReasonML会给出错误的描述信息,甚至可能包含解决问题的提示。也就是说,你可以用试错法来学习类型。

2.2 不支持ad-hoc多态(目前)

ad-hoc多态听起来很赞,虽然目前不支持,但是ReasonML对它已经有一个简单的定义和计划。 ReasonML目前不支持ad-hoc多态(根据不同的参数类型,实现不同的操作)。另一个函数式编程语言Haskell通过类型类(typeclass)来支持ad-hoc多态。ReasonML最终也可能会通过类似的方式来实现对ad-hoc多态的支持。 不支持ad-hoc多态意味着大多数运算符如 + (整数的加法),+. (浮点数加法)和 ++ (字符串连接)只支持单一的数据类型。因此,你需要自己对运算符的数据做适配。不过,如果你忘记了,ReasonML会在编译时提醒你。 这就是静态类型的好处。

3. 注释

在我们继续学习之前,首先让我们来看看如何注释。 ReasonML 只有一种写注释的方法:

/* This is a comment */

可以嵌套注释(C风格的语言通常无法这样使用)这一点是挺方便的。

/* Outer /* inner comment */ comment */

嵌套对于注释代码段非常有用:

/*
foo(); /* foo */
bar(); /* bar */
*/

4. 布尔值

让我们输入一些布尔表达式:

# true;
- : bool = true
# false;
- : bool = false
# !true;
- : bool = false
# true || false;
- : bool = true
# true && false;
- : bool = false

5. 数字

整形数字表达式如下所示:

# 2 + 1;
- : int = 3
# 7 - 3;
- : int = 4
# 2 * 3;
- : int = 6
# 5 / 3;
- : int = 1

浮点数字表达式如下所示:

# 2.0 +. 1.0;
- : float = 3.
# 2. +. 1.;
- : float = 3.
# 2.25 +. 1.25;
- : float = 3.5

# 7. -. 3.;
- : float = 4.
# 2. *. 3.;
- : float = 6.
# 5. /. 3.;
- : float = 1.66666666666666674

6. 字符串

一般字符串使用双引号定义:

# "abc";
- : string = "abc"
# String.length("ü");
- : int = 2

# "abc" ++ "def";
- : string = "abcdef"
# "There are " ++ string_of_int(11 + 5) ++ " books";
- : string = "There are 16 books"

# {| Multi-line
string literal
\ does not escape
|};
- : string = " Multi-line\nstring literal\n\\ does not escape\n"

ReasonML字符串编码为UTF-8,与JavaScript的UTF-16字符串不兼容。ReasonML对Unicode的支持也比JavaScript差。作为一个临时的解决方案,你可以在ReasonML中使用BuckleScript的JavaScript字符串:

Js.log("äöü"); /* garbage */
Js.log({js|äöü|js}); /* äöü */

上面这些字符串通过带有注释的js字面量来定义的,这种用法只有BuckleScript才支持。在原生的ReasonML中,可以得到正常的字符串。

7. 字符

用单引号定义字符。只支持Unicode的前7个字节:

# 'x';
- : char = 'x'
# String.get("abc", 1);
- : char = 'b'
# "abc".[1];
- : char = 'b'
"x".[0] is syntactic sugar for String.get("x", 0).

8. 单元类型

有时候,你需要一个表示“空”的值。 在ReasonML () 就是这样一个特殊的值。() 有它自己的类型:unit 单元类型。() 也是这种类型的唯一取值:

# ();
- : unit = ()

就像 null在C语言中一样,()不属于任何其他类型。 除此之外,单元类型还是没有返回值的函数的默认返回值。 例如:

# print_string;
- : (string) => unit = <fun>

print_string 这个函数只是接收一个字符串并打印,他并没有真正的返回值。

9. 基础类型间的转换

ReasonML’s 的标准库有支持基本类型之间转换的函数:

# string_of_int(123);
- : string = "123"
# string_of_bool(true);
- : string = "true"

所有的类型转换函数都是以下面规则命名。

«outputType»_of_«inputType»

10. 更多运算符

10.1 比较运算符

比较运算符,他们是少数几个可以支持多类型的操作符(多态的)。

# 3.0 < 4.0;
- : bool = true
# 3 < 4;
- : bool = true
# 3 <= 4;
- : bool = true

但是你不能在操作符的两边使用不同类型:

# 3.0 < 4;
Error: Expression has type int but expected type float

10.2 等于运算符

ReasonML有两个相等运算符。 == 用于判断两个值是否相等,当比较的是引用类型(例如列表)时,比较的是他们的值。

# [1,2,3] == [1,2,3];
- : bool = true

与之不同的是,===比较的是引用本身:

# [1,2,3] === [1,2,3];
- : bool = false

除非你真的是想比较引用本身,不然都应该首选 ==

w3ctech微信

扫码关注w3ctech微信公众号

共收到0条回复