OCaml中函数返回列表的反向顺序

5
我想从一个文件中读取一些数字,将它们放入一个列表中,最后在屏幕上显示出来。 numbers.txt 目前有 2 3 5 7 11,然而输出结果是11 7 5 3 2 - : unit = ()。 为什么会这样呢?
let rec int_list_from_sb sb n = 
match n with 
| 0 -> [];
| _ -> (bscanf sb " %d" (fun a -> a))::(int_list_from_sb sb (n - 1));;

let file_name = open_in "numbers.txt" in 
let sb = Scanning.from_channel file_name in 
let int_list = int_list_from_sb sb 5 in
List.iter (fun a -> print_int a) int_list;;
1个回答

5
OCaml中参数的求值顺序是未指定的。因此,当您执行 f x :: g y时,不确定是先调用f还是g。在您的情况下,在调用bscanf之前调用了递归调用,这就是为什么会得到错误顺序结果的原因。
解决求值顺序问题的一般方法是,在需要考虑其副作用顺序的函数参数中将其放入本地变量中。因此,如果您希望先发生f x的影响,然后再调用g,则可以使用let fx = f x in fx :: g y代替f x :: g y
但是在您的情况下,您只需使用bscanf的延续参数即可完成如下操作:
bscanf sb " %d" (fun a -> a :: int_list_from_sb sb (n - 1))

如果在这里选择第二个函数,即递归函数,那么bscanf获取的整数会发生什么? - power_output
@power_output 发生的是 int_list_from_sb 4 被计算,从 sb 中读取 4 个数字并返回 [7; 5; 3; 2],然后 bscanf sb " %d" (fun a -> a) 被计算并返回 11,接着 11 :: [7; 5; 3; 2] 被计算并返回 [11; 7; 5; 3; 2] - sepp2k
@power_output 你很幸运,因为系统刚刚以可预测的方式推迟了扫描。结果(原则上)可能会更有趣,因为sb是一个可变结构:想象一下如果两个表达式被依次评估会发生什么。 - Anton Trunov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接