函数在OCaml中以相反顺序返回列表 [英] function returns list in reverse order in OCaml

查看:73
本文介绍了函数在OCaml中以相反顺序返回列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从文件中读取一些数字,将它们带到列表中,最后在屏幕上显示它们. Numbers.txt当前具有2 3 5 7 11,但是作为输出,我得到11 7 5 3 2 - : unit = ()

I want to read some numbers from a file, take them to a list and finally display them on the screen. numbers.txt currently has 2 3 5 7 11 however as output i'am getting 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;;

推荐答案

在OCaml中未指定参数的求值顺序.因此,当您执行f x :: g y时,不确定首先调用f还是g.在您的情况下,递归调用在调用bscanf之前被调用,这就是为什么您以错误的顺序获得结果的原因.

The order of evaluation of arguments is unspecified in OCaml. So when you do f x :: g y, it is unspecified whether f or g gets called first. In your case the recursive call is invoked before the call to bscanf, which is why you get the results in the wrong order.

解决评估顺序问题的一般方法是,当副作用的顺序很重要时,将函数的参数放入局部变量中.因此,如果希望f x的效果在调用g之前发生,则可以使用let fx = f x in fx :: g y,而不是let fx = f x in fx :: g y.

The general way to fix evaluation-order issues is to put the arguments to a function into local variables when the order of their side effects matters. So instead of f x :: g y, you'd do let fx = f x in fx :: g y if you want the effects of f x to happen before g is called.

但是,在您的情况下,您可以像这样使用bscanf的延续参数:

However in your case you can just make use of bscanf's continuation argument like this:

bscanf sb " %d" (fun a -> a :: int_list_from_sb sb (n - 1))

这篇关于函数在OCaml中以相反顺序返回列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆