我想打印出矩阵的列,但我一直收到错误。
错误:此表达式具有类型'列表,但表达式需要类型为int
let rec get_column2 mat x = match mat with
| [] -> raise (Failure "empty list")
| h::t -> if x = 1 then h else get_column2 t (x-1);;
let rec get_column mat x= match mat with
| [] -> raise (Failure "empty list")
| []::tv -> get_column tv x
| hv::tv -> get_column2 hv x::get_column tv x;;
矩阵示例[[2; 5; 6]; [3; 5; 3] [3; 6; 8]]
第一部分在int类型列表中运行正常,所以我添加了第二部分来遍历int列表并将它们切换到int list' s然后尝试分别获取每个列的列。
我也是这样试过的:
let rec get_column mat x =
let rec column matr y =
if matr = [] then raise (Failure "empty list") else
if y = 1 then List.hd matr else
column (List.tl matr) y-1;
in column (List.hd mat) x :: get_column (List.tl mat) x;;
第二个例子翻译得很好,但后来没有用。我得到了一个例外" tl"。 (我不确定函数嵌套是否正确,因为我只是学习Ocaml)。
答案 0 :(得分:1)
get_column2
- 您的第一个功能,按预期工作。也就是说,它将获取矩阵中每行的值。这是一个很好的帮助函数,您可以从列表中提取值。
你的第二个函数get_column
使所有类型都正确,并且你正在累积所有内容,除了当你有一个空列表[]
而不是停止时,你最终会抛出异常。这就是你的矩阵示例将很好地完成,直到它没有更多的列表可以通过,然后总是抛出异常。 (因为递归一直持续到它是一个空列表,Ocaml也会像你告诉它那样做,当它得到一个空列表时失败。
你唯一缺少的是异常,而不是抛出异常,只返回一个空列表。这样你的递归将一直进行并累积直到它是一个空列表,并且在矩阵为空的最后一步,它会将空列表附加到结果中,而你是金色的。
所以你的代码应该是:
let rec get_column2 mat x = match mat with
| [] -> raise (Failure "empty list")
| h::t -> if x = 1 then h else get_column2 t (x-1)
let rec get_column mat x= match mat with
| [] -> [] (*doesn't throw an exception here*)
| []::tv -> get_column tv x
| hv::tv -> (get_column2 hv x)::get_column tv x
当它是一个空列表时,不是抛出异常,也许你可以检查x的值是否大于内部列表的长度。
此外,这是我的实施。它仍然相当基本,因为它不使用每个人都喜欢的List.iter
,但它不依赖于任何额外的包。它使用嵌套函数,因此您不会在任何地方公开它们并污染命名空间。
(*mat is a list of int list*)
let get_col mat x =
let rec helper rows x = (*helper function that gets the value at x*)
match rows with
| [] -> raise (Failure "empty list")
| h::t -> if x = 1 then h else helper t (x-1)
in
let rec wrapper mat= (*function that walks through all the rows*)
match mat with
| [] -> []
| rows::tl -> (helper rows x)::(wrapper tl) (*keep accumulating value*)
in wrapper mat
如何可视化[] -> []
部分是当递归处于最后阶段(mat减少为空列表)时,包装函数返回空列表,该列表将附加到递归堆栈(因为我们按照(helper rows x)::(wrapper tl)
在列表中累积值),递归将完成。
当你告诉ocaml停止递归并且在x = 1时返回一个值时,你不会使用get_column2
来发现此错误。
修改,附加:
正如Jeffrey所提到的,处理错误的一种更优雅的方法是为[row]
添加大小写,其中row是矩阵中的最后一行。你只需返回(辅助行x)。你可以将空矩阵作为失败。
使用您的代码的示例:
let rec get_column mat x= match mat with
| [] -> raise (Failure "empty list") (*fail here, as we don't want to compute a matrix with no rows.*)
| [tv] -> get_column tv x (*just return the value*)
| hv::tv -> (get_column2 hv x)::get_column tv x
答案 1 :(得分:0)
当我尝试你的第一个例子时,我没有收到类型错误。当我运行它时,我得到了#34;空列表"失败。所以你对问题的描述似乎是错误的。
如果要将空矩阵视为错误,则必须非常小心处理1 x n矩阵作为基本情况。我在你的代码中没有看到它。