这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战」
参数标记和可选参数
对于参数比较多的函数(尤其是那些有相同类型参数),可以使用标记。OCaml支持对函数的参数进行标记。比如:
utop # let f ~name1: arg1 ~name2:arg2 = arg1 + arg2;;
val f : name1:int -> name2:int -> int = <fun>
utop # f ~name2: 3 ~name1: 4;;
- : int = 7
参数的标记通常和变量名一样。OCaml 提供对待两者是一样的,如下面的代码是等价的
utop # let f ~name1: name1 ~name2: name2 = name1 + name2;;
utop # let f ~name1 ~name2 = name1 + name2;;
也支持对参数指定显式的类型
utop # let f ~name1:(arg1:int) ~name2:(arg2:int) = arg1 + arg2;;
当然有些参数是可选的,
utop # let f ?name: (arg1=8) arg2 = arg1 + arg2;;
val f : ?name:int -> int -> int = <fun>
utop # f ~name:2 7;;
- : int = 9
utop # f 7;;
- : int = 15
Partial application
比如,下面有两个函数
utop # let add x y = x + y;;
utop # let addx x = fun y -> x + y;;
其中,函数addx的类型是 int -> int -> int;而 add的类型也为int -> int -> int。从这一点上可以看出它们是相同的函数。但是addx的形式很有趣,它仅仅只需要复制给一个参数。
utop # let add5 = addx 5;;
val add5 : int -> int = <fun>
utop # add5 2;;
- : int = 7
并且使用add也可以达到相同的效果
utop # let add5 = add 5;;
val add5 : int -> int = <fun>
utop # add5 2;;
- : int = 7
这就是所谓的partial application: 我们能够调用函数的时候只传递部分参数。为什么这是OK的?因为下面的三个函数在语法上不同但是语义是相同的。换句话说,就是用不同的方法来表示相同的计算式:
utop # let add x y = x + y;;
utop # let add x = fun y -> x + y;;
utop # let add = fun x -> (fun y -> x + y);;
OCaml中的每一个函数仅仅只有一个参数
为什么?通常来说,
let f x1 x2 ... xn = e;;
在语法上等同于
let f =
fun x1 ->
(fun x2 ->
(...
(fun xn -> e)...))
所以,可以认为函数f有n个参数,等同于这个函数只有一个参数,并返回一个函数,并且这个函数的类型为
t1 -> t2 -> t3 -> t4
更严谨点说是,
t1 -> (t2 -> (t3 -> t4)))
这被称作类型的右结合率。
操作符可以被看作成函数
The addition operator + has type int->int->int. It is normally written infix, e.g., 3+4. By putting parentheses around it, we can make it a prefix operator:
# (+);;
- : int -> int -> int = <fun>
# (+) 3 4;;
- : int = 7
# let add3 = (+) 3;;
- : int -> int = <fun>
# add3 2;;
- : int = 5
let 表达式
syntax
let x = e1 in e2
Dynamic sematics:
为了计算let x = e1 in e2:
-
计算
e1得到值v1 -
用
v1替代e2中的x,产生一个新值e2' -
计算
e2'得到v2 -
整个表达式的值为
v2
utop # let x = 1 + 4 in x * 3;;
- : int = 15
Static semantics.
- If
e1:t1and if under the assumption thatx:t1it holds thate2:t2, then(let x = e1 in e2) : t2.
\