OCaml变量计数

OCaml变量计数,ocaml,Ocaml,我试图实现以下目标:在特定索引处查找元素 因此,如果我有一个[5;2;3;6]列表,并请求索引2处的元素,它将返回3 let counter = 0;; let increase_counter c = c + 1;; let rec get_val x n = match x with [] -> -1 | (h::t) -> if (counter = n) then h else increase_counter counte

我试图实现以下目标:在特定索引处查找元素

因此,如果我有一个
[5;2;3;6]
列表,并请求索引
2
处的元素,它将返回
3

let counter = 0;;
let increase_counter c = c + 1;;
let rec get_val x n = match x with
    [] -> -1
  | (h::t) ->
    if (counter = n) then
      h
    else
      increase_counter counter ; get_val t n
;;

但是这段代码给了我一个错误,说
-1
不是'unit'类型?

这段代码有很多问题。如果您暂时忽略了眼前的问题,那么您将OCaml变量视为命令式语言的变量。但是,OCaml变量是不可变的。此函数

let increase_counter c = c + 1
不会更改任何变量的值。它只返回一个比你给它的值大的数字1

输入代码时,我从顶层得到的唯一错误是此表达式:

  increase_counter counter ; get_val t n

编译器警告您,
之前的表达式
应该因其副作用而执行。也就是说,它应该几乎总是有类型
单元
。因为(正如我所说)您的函数
increase\u counter
返回一个int,所以编译器警告您这一点。

正如Jeffrey Scofield所说,您应该编写
let counter=ref 0
,以使
counter
可变。现在,您可以使用内置的
incr
函数对其进行递增(相当于
计数器:=!计数器+1
),您将通过
获得其值!计数器

算法中还有一个问题:如果计数器等于
n
,则返回列表的标题。。。您的意思是:如果列表的标题等于
n
,则返回计数器

您的计划是:

let counter = ref 0;;

let rec get_val x n = match x with
    [] -> -1
  | (h::t) ->
    if (h = n) then
      !counter
    else
      begin incr counter ; get_val t n end
;;
请注意,我在else块周围添加了
begin
end
,因此可以将其解释为一系列指令

您的程序现在可以工作了,但这不是使用ocaml解决此问题的最佳方法

你应该写一些类似的东西

let get_val x n =
  let rec get_val_aux x n counter = match x with
    | [] -> -1
    | h :: _ when h = n -> counter
    | _ :: t -> get_val_aux t n (succ counter)
  in
    get_val_aux x n 0
;;
在这里,我们向
get\u val\u aux
函数添加一个参数,在每次调用时递增该参数。此函数嵌套在
get_val
函数中,用于隐藏在第一次调用时用
0
初始化的附加参数

我们不使用
if
语句,而是使用
when
条件来知道何时找到元素,并添加一个新的case以匹配上一个case(未找到)。注意使用
\uu
通配符以避免未使用的变量


succ
函数(对于后继函数)仅向其参数添加
1
。这相当于
计数器+1

OCaml变量是不可变的,您不能更改它们的值!:-)我会寻找另一种方法来实现这一点(也许是函数的一个额外参数)。但是,如果您坚持必须编程,则需要使用引用(
let counter=ref 0
)。哈哈,好的,谢谢。我太习惯命令式语言了,我想不出任何其他的方法。等等,但是如果我让x=1,然后让x=5,然后打印它打印的是5而不是1,那么我没有改变变量吗?它没有改变变量。您有两个同名的不同变量。旧变量仍然存在。请参阅本SO页面,了解更多关于此方面的说明: