我正在尝试实现以下目的:在特定索引处查找元素。
因此,如果我有一个[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'?
答案 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
。