# 函数式编程

## 什么是函数式编程

``````# let double x = x * 2 in
List.map double [ 1; 2; 3 ];;- : int list = [2; 4; 6]
``````

`map`被称为高阶函数（higher-order function） (HOF)。高阶函数是指一个把其他函数作为参数之一的函数。

``````# let multiply n list =
let f x =
n * x in
List.map f list;;val multiply : int -> int list -> int list = <fun>
``````

``````# multiply 2 [1; 2; 3];;- : int list = [2; 4; 6]
# multiply 5 [1; 2; 3];;- : int list = [5; 10; 15]
``````

`map` 的定义在`List`模块中，离当前的代码很远。也就是说，我们把`f` 传递到一个”很久很久以前，在一个很遥远很遥远的星系“（译者：星球大战片头）中的一个模块。 代码可以传递`f`给其他模块，或者把它的引用（reference）在某个地方以便之后 再调用它。不管怎样，这个闭包保证`f`总是可以获取它定义时的环境，比如`n`

``````class html_skel obj = object (self)
...
...
method save_to_channel chan =
output_string chan content;
true in
...
end``````

## 偏函数应用（Partial function applications）和 currying（科里化）

``````# let plus a b =
a + b;;val plus : int -> int -> int = <fun>
``````

1. 什么是`plus`?
2. 什么是`plus 2 3`?
3. 什么是`plus 2`?

``plus : int -> int -> int``

``5 : int``

``````# plus 2;;- : int -> int = <fun>
``````

``````# let f = plus 2;;val f : int -> int = <fun>
# f 10;;- : int = 12
# f 15;;- : int = 17
# f 99;;- : int = 101
``````

``````let plus 2 b =       (* 这不是真正的OCaml代码！ *)
2 + b``````

``````    plus : int -> int -> int
plus 2 : int -> int
plus 2 3 : int``````

``````# let multiply n list =
let f x =
n * x in
List.map f list;;val multiply : int -> int list -> int list = <fun>
``````

``````# let double = multiply 2;;val double : int list -> int list = <fun>
# let triple = multiply 3;;val triple : int list -> int list = <fun>
``````

``````# double [1; 2; 3];;- : int list = [2; 4; 6]
# triple [1; 2; 3];;- : int list = [3; 6; 9]
``````

``````# let multiply n = List.map (( * ) n);;val multiply : int -> int list -> int list = <fun>
# let double = multiply 2;;val double : int list -> int list = <fun>
# let triple = multiply 3;;val triple : int list -> int list = <fun>
# double [1; 2; 3];;- : int list = [2; 4; 6]
# triple [1; 2; 3];;- : int list = [3; 6; 9]
``````

``````# let plus = ( + );;val plus : int -> int -> int = <fun>
# plus 2 3;;- : int = 5
``````

``````# List.map (plus 2) [1; 2; 3];;- : int list = [3; 4; 5]
# let list_of_functions = List.map plus [1; 2; 3];;val list_of_functions : (int -> int) list = [<fun>; <fun>; <fun>]
``````

## 纯函数式和非纯函数式编程

``````for (i = 0; i < strlen (s); ++i)
{
// Do something which doesn't affect s.
}``````

## 非懒惰和懒惰

``````# let give_me_a_three _ = 3;;val give_me_a_three : 'a -> int = <fun>
# give_me_a_three (1/0);;Exception: Division_by_zero.
``````

OCaml是一个非懒惰的语言，但是`Lazy`模块允许你写懒惰的表达式，下面就是这样一个例子：

``````# let lazy_expr = lazy (1/0);;val lazy_expr : int lazy_t = <lazy>
``````

``````# give_me_a_three lazy_expr;;- : int = 3
``````

``````# Lazy.force lazy_expr;;Exception: Division_by_zero.
``````

## box和unbox类型

``````#include <stdio.h>

void
printit (int *ptr)
{
printf ("the number is %d\n", *ptr);
}

void
main ()
{
int a = 3;
int *p = &a;

printit (p);
}``````

`a`是在栈上的，显然是unboxed的。