OCaml Introduction and Basics of OCaml (二)

222 阅读2分钟

这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战

If 表达式

if e1 then e2 else e3

相当于 如果e1为真就返回e2否则为e3

utop # if 3 + 5 > 2 then "yay!" else "bool";;
- : string = "yay!"

if-then-else 可以将其放在任何地方,有点像?:

utop # 4 + ( if 'a' = 'b' then 1 else 2 );;
- : int = 6

当然也可以进行嵌套

if e1 then e2
else if e3 then e4
else if e5 then e6
...
else en

值得注意的是最后的else是强制的,如果不加else将会报错

utop # if 2 > 3 then 5;;
Error: This expression has type int but an expression was expected of type 
       unit because it is in the result of a conditional with no else branch

Syntax : If 表达式的句法

if e1 then e2 else e3

其中字母e用来表示其他的OCaml表达式;是一种句法变量/元变量(aka, metavariable),其实在OCaml中这不是真正的变了,而是一个名字或者说一种特定的语法结构。

动态语义

  • if e1 evaluates to true, and if e2 evaluates to a value v, then if e1 then e2 else e3 evaluates to v
  • if e1 evaluates to false, and if e3 evaluates to a value v, then if e1 then e2 else e3 evaluates to v.

静态语义

  • if e1 has type bool and e2 has type t and e3 has type t then if e1 then e2 else e3 has type t

type rule : 用来如何判断表达式的类型。

函数定义

utop # let x = 42;;
val x : int = 42

上面这段代码中, (42)不是表达式,而是一种 定义. 定义绑定值和名字 ,在上面的例子中,值 42 被赋予名字 x.定义不是表达式,也不是表达式的声明-这用来区分于语法上的类。并且,定义中可以有表达式嵌套在里面,反之亦然。

函数定义是一种特殊的定义,非递归函数的定义如下:

let f x = ...

递归函数的定义如下

let rec f x = ...

PS: 其他语言中默认将函数认为是递归函数,而OCaml则将其分开

如下面是一个阶乘函数的定义:

utop # let rec fact n = if n=0 then 1 else n * fact(n -1);;
val fact : int -> int = <fun>

let rec pow x y =
          if y = 0 then 1
          else x * pow x (y - 1);;
val pow : int -> int -> int = <fun>


utop # let rec pow (x: int) (y : int) : int = 
           if y = 0 then 1
           else x * pow x (y - 1);;
val pow : int -> int -> int = <fun>

匿名函数

fun x1 ... xn -> e

函数调用

e0 e1 e2 ... en

pipeline operator |> , 暗示值将会从左到右送进pipeline。假设我们有两个函数inc:加一操作和square:求平方。

utop # let inc x = x + 1;;
utop # let square x = x * x;;
utop # 5 |> inc |> square;;
- : int = 36
utop # square(inc(5));;
- : int = 36
utop # 5 |> inc |> square |> inc |> inc |> square;;
- : int = 1444

多态函数

 utop # let id x = x;;
 val id : 'a -> 'a = <fun>

注意到,'a 是 类型变量: 这代表是不知道的类型。类型变量通常有一个单引号开始。