如何在Ocaml中获取矩阵的列

时间:2015-04-15 16:25:16

标签: recursion ocaml

我想打印出矩阵的列,但我一直收到错误。

错误:此表达式具有类型'列表,但表达式需要类型为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)。

2 个答案:

答案 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矩阵作为基本情况。我在你的代码中没有看到它。