1.2

1.2

野指针

## 2.ocaml上编程的第一步


你现在可以在OCmal上写属于自己的第一行代码了!首先我们要打开一个编译器(最好是utop,但也可以是ocaml或者一个在线编译器)。


在编译器中,所有的命令都要以 ;; 结尾(两个分号)。由此OCmal才能分辩哪里是命令的结尾并开始执行命令。但如果你是写在一个文件(file)中的话,一般而言是不需要的。


尝试输入一个简单的计算命令(敲击回车执行):

```ocaml

 2 + 2;; 

 ```

通常来讲,编译器会返回以下内容:

```ocaml

- :int = 4

```

对于目前来说,我们只关注`=`右边:我们的计算式成功运行了,2加2等于4。这是一个良好的开端!你接下来可以尝试一些其它的运算符号,比如`*`或者是`-`。


然而,对于某些运算符来说,有些小细节希望你能知道:

   

  - `/`用来计算商(类比Python中的`//`)。所以它的结果会是一个整数。

  

  - `mod`类比于Python中的`%`用来计算余数。  


毫无疑问地来讲,现在最令你感到疑惑的一定是:这些操作符并不适用于浮点数(带小数点的数字)。举个例子,如果你输入了下面这个算术式,你会得到一个错误提示:

```ocaml

   (*从现在起,我不会再写;;,但是如果需要的话,别忘了加上*)

   2.8 + 0.2

```

为了理解为什么我们会得到一个错误提示,我们要弄清楚表达式以及类型的定义。


**表达式**是计算机可以编译和计算的一段代码,由此可以计算它的值。


在OCaml中,全部或者说是几乎是全部的代码有表达式构成。

但在此,我举一个Python中的例子:


```python

12 #这是一个表达式,其值为12

12 + 7 #这是一个表达式,其值为19(在此指出,这个表达式是由两个更简单的表达式 7 和 12 组成的。)

print(“你好!”) #这也是一个表达式,尽管其值为None(没有值)

a = 12 #本行不是一个表达式,“a = 12”并不是一个值, 这是一个指令。

```

更通俗来讲,当你想判断眼前的语句是不是一个表达式时,不妨问问自己:

“我可以将这个值存于一个变量中吗?”

从以下三个例子中,我门可以很清楚地发现,对于前两行来说,答案是“可以”。但是对于最后一行来说并不太可行。


```python

x = (12 + 7) #没有问题

y = (print("你好!")) #虽然这看起来有点奇怪,因为在这个变量中的值为<没有值>,但是是可行的。

z = (a = 12) #尽管在另一种情况下这看起来可能合乎逻辑, 但"a = 12"并不是一个值,我们不能将它储存在变量中。

```


现在我们将讨论有关类型的问题。**类型**是有关表达式的一项信息,它可以告诉我们表达式中可以储存的值。这有点像数学中集合的概念。毫无疑问,我们已经见到过Python中的几种类型, 比如'int'或者是'float'或者是'str'。在OCaml中,我们也仍然会看到这些类型,但是OCaml的类型体系相较于Python中更进了一步。在OCaml中,所有的表达式都有其定义好的类型:我们称之为*静态类型*语言。


但所有的这些并不能解释为什么两个小数相加会导致错误。

原因是因为OCaml中的运算符号`+`适用于其两侧均为`int`的表达式语句中,否则不适用。

对于`-`、`*`、`/`以及`mod`也是同样的道理。对于浮点数而言,我们有不同的操作符:`+.`、`-.`、`*.`、`/.`以及`mod_float`。



但是为什么要复杂化这些呢?Python即使不区分这两种操作符也运行的很好,为什么OCaml不这样做呢?


OCaml非常重视类型,它需要每时每刻都知道表达式的类型。它不能对此模糊不清。同样的,这也可以保证在运行前,代码行中没有错误。

在Python中运行以下语句:

```python

liste = [1, 2, 3]

liste + "Oups" #使一个列表和一个文本相加?🤔️

```

在类型方面,Python并不像OCaml一样严格,它会在不提出疑问的情况下运行这个程序,并且当问题行被运行时,它并不会显示出错误。在这个例子中,问题可以很快被发现,但是想象一下同样的问题出现在成百上千的代码行中间、在极其复杂的函数中间……

总而言之,寻找错误的源头是个噩梦!


在OCaml中,如果你想尝试做这种类型的操作,你会在代码运行之前立马得到一个**类型错误**,这样就可以提前避免大量的错误!


但是为了确认这些类型,OCaml需要知道每个表达式的类型。

在这项任务中,正确使用操作符会很有帮助:加法`+`适用于`int`类型,加法`+.`适用于`float`类型。

这就是为什么我们不能在各个地方使用同样的操作符的原因!


Report Page