OCaml变量计数

时间:2014-03-21 17:04:42

标签: 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 counter ; get_val t n
;;

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

2 个答案:

答案 0 :(得分:1)

此代码存在许多问题。如果您暂时忽略了您的直接问题,那么您将OCaml变量视为命令式语言的变量。但是,OCaml变量是不可变的。这个功能

let increase_counter c = c + 1

不会更改任何变量的值。它只返回比你给它的数字大1的数字。

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

  increase_counter counter ; get_val t n

编译器警告您;之前的表达式应该针对其副作用执行。即,它应该几乎总是具有类型unit。由于(正如我所说)你的函数increase_counter返回一个int,编译器会警告你这个。

答案 1 :(得分:1)

正如Jeffrey Scofield所说,你应该写let counter = ref 0来使counter变得可变。现在,您可以使用内置的incr函数来递增它(相当于counter := !counter + 1),并且您将使用!counter获取其值。

您的算法中也存在一个问题:如果计数器等于n,则返回列表的头部...您的意思是:如果列表的头部等于{{1}你返回柜台。

您的计划是:

n

请注意,我已在else块周围添加了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 ;; begin,因此可以将其解释为一系列指令。

您的程序现在可以正常运行,但这不是使用ocaml解决此问题的最佳方法。

你应该写点像

end

在这里,我们向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_val_aux函数中,以隐藏在第一次调用时使用get_val初始化的附加参数。

我们不使用0语句,而是使用if条件来了解元素何时被找到,并添加一个新案例以匹配最后一个案例(未找到)。请注意使用when通配符来避免使用未使用的变量。

_函数(对于后继者)仅将succ添加到其参数中。它相当于1