JSRUN 用代码说话

高阶函数

编辑教程

高阶函数

即使引发异常,也要处理系统资源

即使治疗引发异常,也可以使用高阶函数来确保处理系统资源。 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 ++的用户可以将其与策略模式进行比较。

JSRUN闪电教程系统是国内最先开创的教程维护系统, 所有工程师都可以参与共同维护的闪电教程,让知识的积累变得统一完整、自成体系。 大家可以一起参与进共编,让零散的知识点帮助更多的人。
X
支付宝
9.99
无法付款,请点击这里
金额: 0
备注:
转账时请填写正确的金额和备注信息,到账由人工处理,可能需要较长时间
如有疑问请联系QQ:565830900
正在生成二维码, 此过程可能需要15秒钟