了解两个尾递归映射函数的性能差异
Understanding the performance difference of two tail recursive map functions
来自 Jason Hickey 对 Objective Caml 的介绍,我们有一个尾递归映射函数:
let rec rev_accum result = function
h::tl -> rev_accum (h :: result) tl
| [] -> result
let rec rec_map f result = function
h :: tl -> rec_map f (f h :: result) tl
| [] -> result
let map1 f l = rev_accum [] ( rec_map f [] l )
它将遍历列表两次。考虑这个替代方案:
let rec rec_map2 f result = function
h :: tl -> rec_map2 f ( result @[f h]) tl
| [] -> result
let map2 f l = rec_map2 f [] l ;
第二个会比第一个快吗?
重复添加到列表末尾所花费的时间是列表最终长度的二次方。另一种说法是它遍历列表 n 次,这很容易超过两次。所以第二个实现一般来说会慢很多。第一个实现是线性的,即使它遍历列表两次。
(当然你不知道函数f
的性能)
来自 Jason Hickey 对 Objective Caml 的介绍,我们有一个尾递归映射函数:
let rec rev_accum result = function
h::tl -> rev_accum (h :: result) tl
| [] -> result
let rec rec_map f result = function
h :: tl -> rec_map f (f h :: result) tl
| [] -> result
let map1 f l = rev_accum [] ( rec_map f [] l )
它将遍历列表两次。考虑这个替代方案:
let rec rec_map2 f result = function
h :: tl -> rec_map2 f ( result @[f h]) tl
| [] -> result
let map2 f l = rec_map2 f [] l ;
第二个会比第一个快吗?
重复添加到列表末尾所花费的时间是列表最终长度的二次方。另一种说法是它遍历列表 n 次,这很容易超过两次。所以第二个实现一般来说会慢很多。第一个实现是线性的,即使它遍历列表两次。
(当然你不知道函数f
的性能)