我试图在一个for循环中添加一个类型(int * int)的元组到列表,但我得到一个错误说:这个表达式应该有类型单位 .
这就是我现在所拥有的:
let addtuple k lst = for i=0 to k - 1 do let (n,j) =Scanf.scanf " %d %d" (fun a b->(a,b)) in (n,j)::lst done;;
OCaml for 的目的是做某事,而不是计算一个值 . 所以循环体应该是一个OCaml表达式,它具有有用的副作用(比如打印一个值) . 因此, for 循环的主体应该具有 unit 类型,该类型用于没有有趣值的表达式 . 但是你的循环有一个列表的主体 . 编译器正在告诉你(正确)这表明出现了问题 .
for
unit
假设表达式 (n, j) :: lst 将更改 lst 的值,则编写代码 . 但这种情况并非如此 . 在像OCaml这样的函数式语言中,您无法更改变量的值 .
(n, j) :: lst
lst
如果你的函数应该返回一个列表,它不能基于 for 循环,它总是返回 () (类型单位的唯一值) . 最有可能的是它应该基于折叠(在处理一系列输入时累积值)或者基于您自己的递归函数 .
()
使用 for ,您需要使用 ref :
ref
let addtuple k lst = let r = ref lst in for i = 1 to k do r := (Scanf.scanf " %d %d" (fun x y -> (x, y))) :: !r done; !r;;
使用递归函数的更实用的方法:
let rec addtuple k lst = match k with | 0 -> lst | _ -> addtuple (k - 1) ((Scanf.scanf " %d %d" (fun x y -> (x, y))) :: lst);;
2 回答
OCaml
for
的目的是做某事,而不是计算一个值 . 所以循环体应该是一个OCaml表达式,它具有有用的副作用(比如打印一个值) . 因此,for
循环的主体应该具有unit
类型,该类型用于没有有趣值的表达式 . 但是你的循环有一个列表的主体 . 编译器正在告诉你(正确)这表明出现了问题 .假设表达式
(n, j) :: lst
将更改lst
的值,则编写代码 . 但这种情况并非如此 . 在像OCaml这样的函数式语言中,您无法更改变量的值 .如果你的函数应该返回一个列表,它不能基于
for
循环,它总是返回()
(类型单位的唯一值) . 最有可能的是它应该基于折叠(在处理一系列输入时累积值)或者基于您自己的递归函数 .使用
for
,您需要使用ref
:使用递归函数的更实用的方法: