我正在编写应该以列表为输入并返回新列表作为输出的代码,其中对于每个索引,该索引处的值是输入列表中先前元素的总和。
这是我到目前为止所得到的:
let counter1 = ref 0;;
let rec sumthingy = fun list ->
match list with
| [] -> []
| [a] -> [a]
| hd::tl -> if List.length list > !counter1
then (counter1:=!counter1 + 1 ;
[ (sum list !counter1 ) ] @ sumthingy list)
else [];;
let total = ref 0;;
let counter = ref 0;;
let rec sum = fun list n ->
match list with
| [] -> !total
| [a] -> if !counter != n then
(counter:= !counter + 1;
total:= !total + a;
!total) else !total
| hd::tl -> if !counter != n then
(counter:= !counter + 1;
total:= !total + hd;
sum tl n) else !total;;
sum [1;2;3] 1;;
sumthingy [1;2;3];;
函数“ sum”本身可以正常工作,因此问题必须出在“ sumthingy”中。
[1; 2; 3]的预期输出为[1; 3; 6],但由于某种原因我得到了[6; 6; 6]。
注意:我知道计数器的索引不准确。 sum [1; 2; 3] 1应该输出3,但是输出1。对于我来说,这不是什么大不了的事,我只想让它工作。
答案 0 :(得分:0)
考虑以下表达式:
[ (sum list !counter1 ) ] @ sumthingy list
因为您正在编写命令式代码(带有副作用),所以结果取决于@
左侧和右侧的求值顺序。但是OCaml不能保证评估顺序。
我的猜测是订单不符合您的预期。
您可以使用let
担保订单:
let x = expr1 in
let y = expr2 in
x @ y
这保证expr1
在expr2
之前被评估。
(一个更好的解决方案是编写没有副作用的代码:-)
答案 1 :(得分:0)
在我看来,您正在以非常复杂的方式解决任务。这既不是惯用的,也很难阅读/调试。
我将首先采用一个简单的解决方案:
实现给定列表的函数,并且n返回从0到第n的列表元素之和
将函数从(1)馈送到map
,并获得所需的结果。
类似
let sum lst n =
let rec aux lst s m =
match lst, m with
| [], _ -> s
| hd::tl, 0 -> s+hd
| hd::tl, _ -> aux tl (s+hd) (m-1)
in
aux lst 0 n
;;
let sumthingy lst =
List.mapi (fun i _ -> sum lst i) lst
;;
utop # sumthingy [1;3;5;7];;
- : int list = [1; 4; 9; 16]
这个解决方案远非最佳方案-尽管从头开始计算总和,尽管事实是,对于每个元素,我们已经计算出前一个元素的总和,所以理想情况下,我们只需要执行1个和运算就可以得到每个下一个元素。但这应该足以作为起点...