高阶函数
编辑教程高阶函数
即使引发异常,也要处理系统资源
即使治疗引发异常,也可以使用高阶函数来确保处理系统资源。 with_output_file使用的with_output_file允许清晰地分离关注点:高阶with_output_file函数负责管理绑定到文件操作的系统资源,而处理f仅消耗输出通道。
let with_output_file path f =
let c = open_out path in
try
let answer = f c in
(close_out c; answer)
with exn -> (close_out c; raise exn)
让我们使用这个高阶函数来实现一个将字符串写入文件的函数:
let save_string path s =
(with_output_file path) (fun c -> output_string c s)
使用比fun c -> output_string cs更高级的函数,可以保存更复杂的值。
组合运营商
两个有用的高阶函数是二进制应用程序 ( @@ )和反向应用程序或“管道”( |> )运算符。虽然从4.01开始它们可以作为基元使用,但在这里定义它们仍然是有益的:
let (|>) x f = f x
let (@@) f x = f x
考虑增加3的平方的问题。表达该计算的一种方法是:
(* 1 -- Using parentheses *)
succ (square 3)
(* - : int = 10 *)
(* where `square` is defined as: *)
let square x = x * x
请注意,我们不能简单地执行succ square 3因为(由于左关联性 )会减少到无意义的(succ square) 3 。使用application( @@ )我们可以在没有括号的情况下表达:
(* 2 -- Using the application operator *)
succ @@ square 3
(* - : int = 10 *)
注意如何在表达式中首先执行最后一个操作(即succ )? 反向应用程序运算符( |> )允许我们反过来:
(* 3 -- Using the reverse-application operator *)
3 |> square |> succ
(* - : int = 10 *)
数字3现在通过square “管道”然后是succ ,而不是应用于square以产生应用succ的结果。
通用算法
高阶函数可用于实现通用算法,放弃向用户提供最终细节的责任。例如, List.sort需要一个比较函数,它允许实现各种排序方式。这里我们实现了对字符串不区分大小写的排序:
let string_case_insensitive_sort lst =
let case_insensitive_compare a b =
String.compare (String.lowercase a) (String.lowercase b)
in
List.sort case_insensitive_compare lst
标准库中有一个丰富的高阶函数列表 ,特别是在List模块中,例如参见List.fold_left和List.sort 。可以在第三方库中找到更高级的示例。一个很好的例子是在ocaml-gsl中实现的模拟退火 。 模拟退火是一种通用的优化程序,它通过用于探索问题状态集和误差函数(此处称为能量函数)的函数进行参数化。
熟悉C ++的用户可以将其与策略模式进行比较。
选择支付方式:
备注:
转账时请填写正确的金额和备注信息,到账由人工处理,可能需要较长时间