gpt4 book ai didi

ocaml - 在 OCaml 中总结列表的最惯用(或最快)的方法是什么?

转载 作者:行者123 更新时间:2023-12-04 16:44:38 25 4
gpt4 key购买 nike

这是我要实现的

功能方式

let sum l = List.fold_left (fun s x -> s+x) 0 l

命令式方式
let sum l =
let sum = ref 0 in
List.iter (fun x -> sum := !sum +x) l;
!sum

有没有更好/更快的方法来做到这一点?

我问这个是因为书 Real World OCaml说:
# let sum list =
let sum = ref 0 in
List.iter list ~f:(fun x -> sum := !sum + x);
!sum
;;
val sum : int list -> int = <fun>
This isn't the most idiomatic (or the fastest) way to sum up a list, but it shows how you can use a ref in place of a mutable variable.

最佳答案

这稍微凉了点;)

let sum l = List.fold_left (+) 0 l;;

查看性能:
open Printf

let sum1 l = List.fold_left (fun s x -> s+x) 0 l;;
let sum2 l = List.fold_left (+) 0 l;;
let sum3 = List.fold_left (+) 0;;

let rec make_list x acc = function
| 0 -> acc
| n -> make_list x (x :: acc) (n-1)

let l = make_list 1 [] 50000000;;

let _ = match Sys.argv.(1) with
| "1" -> printf "%d\n" (sum1 l)
| "2" -> printf "%d\n" (sum2 l)
| "3" -> printf "%d\n" (sum3 l)
| _ -> printf "Bad arg\n"
;;

给予
$ ocamlc foo.ml
$ time ./a.out 1
50000000

real 0m8.204s
user 0m7.211s
sys 0m0.848s
$ time ./a.out 2
time ./a.out 3
50000000

real 0m8.226s
user 0m7.325s
sys 0m0.818s
$ 50000000

real 0m8.472s
user 0m7.561s
sys 0m0.837s

sum1 和 sum2 具有完全相同的字节码:
    branch L2
restart
L3: grab 1
acc 1
push
acc 1
addint
return 2
L1: acc 0
push
const 0
push
closure L3, 0
push
getglobal List!
getfield 14
appterm 3, 4
L2: closure L1, 0
push
acc 0
makeblock 1, 0
pop 1
setglobal Foo1!

sum3 的字节码较小,但速度较慢
    branch L2
restart
L1: grab 1
acc 1
push
acc 1
addint
return 2
L2: const 0
push
closure L1, 0
push
getglobal List!
getfield 14
apply 2
push
acc 0
makeblock 1, 0
pop 1
setglobal Foo3!

有谁知道为什么?

关于ocaml - 在 OCaml 中总结列表的最惯用(或最快)的方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19430900/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com