我正在编写一个带有一对列表的函数,如果两个列表的长度相等,那么从每个列表中创建一对每个元素,但我的函数不起作用,编译器说有一个语法错误
有人可以解释为什么函数末尾的分号会出现语法错误吗?
这是我的代码:
let define_tuple a b =
(a, b);;
let zip (a, b) =
if List.length (fst (a, b)) != List.length (fst (a, b))
then
printf_string "lengths of 2 lists need to be equal"
else
let rec create_tuples (a, b) =
if List.length (List.tl (fst (a, b))) = 0 && List.length (List.tl (snd (a, b))) != 0
then
[]
else
List.append define_tuple (List.hd (fst (a, b))) (List.hd (snd (a, b))) create_tuples (List.tl (fst (a, b)), List.tl (snd (a, b)));;
zip ([1; 2; 3], [2; 3; 4]);;
答案 0 :(得分:2)
您的代码中存在相当多的可能改进和错误,我将其列在以下所有内容中:
否。 1 强>
如果您在一个文件中编写代码并尝试编译/运行您的文件,那么您最终不需要;;
来为每个函数。
否。 2 强>
let define_tuple a b = (a, b);;
您无需定义此类功能,而是可以直接使用(a, b)
。
否。 3 强>
let zip (a, b) =
if List.length (fst (a, b)) != List.length (fst (a, b)) then
printf_string "lengths of 2 lists need to be equal"
else
let rec create_tuples (a, b) =
if List.length (List.tl (fst (a, b))) = 0 && List.length (List.tl (snd (a, b))) != 0
then
[]
else
List.append define_tuple (List.hd (fst (a, b))) (List.hd (snd (a, b))) create_tuples (List.tl (fst (a, b)), List.tl (snd (a, b)));;
<强> 3.1 强>
对于您的第一个if ... else ...
,它不正确,因为if
分支返回unit
并且else
分支返回list
。
在OCaml中,if
和else
或模式匹配的任何分支都应返回相同的类型。
<强> 3.2 强>
由于 3.1 ,我建议你为non-equal lengths
案例写一个例外。通过这种方式,整个函数仍然返回列表,代码更具可读性,函数用户也可以“抓住”您的异常情况。
<强> 3.3 强>
表示函数create_tuples
,
let rec create_tuples (a, b) =
if List.length (List.tl (fst (a, b))) = 0 && List.length (List.tl (snd (a, b))) != 0
then
[]
else
List.append define_tuple (List.hd (fst (a, b))) (List.hd (snd (a, b))) create_tuples (List.tl (fst (a, b)), List.tl (snd (a, b)));;
<强> 3.3.1 强>
List.length (List.tl (fst (a, b))) = 0
您不需要使用fst (a,b)
,只需a
即可,因为a已经知道。
snd
用法相同。
基本上,您的代码不需要fst
和snd
。
<强> 3.3.1.1 强>
您应该检查a
和b
的长度是否为0,而不是tl
。
<强> 3.3.2 强>
您也不需要(a,b)
元组作为create_tuples
的参数,而是可以使用create_tuples a b
。它更好,因为您的代码不需要为一对参数创建元组。
<强> 3.3.3 强>
List.append define_tuple (List.hd (fst (a, b))) (List.hd (snd (a, b))) create_tuples (List.tl (fst (a, b)), List.tl (snd (a, b)))
首先,List.append
是将一个列表附加到另一个列表。在您的情况下,您要在列表中添加元素,因此您应该使用::
。
如果要使用函数应用程序的值,则应使用()
包含函数应用程序。
(define_tuple (List.hd (fst (a, b))) (List.hd (snd (a, b)))):: (create_tuples (List.tl (fst (a, b)), List.tl (snd (a, b))))
。
如果你一起考虑以前的观点,你可以做到
(List.hd a, List.hd b)::(create_tuples (List.tl a) (List.tl b))
<强> 3.4 强>
您已定义了函数create_tuples
,但您是否真的在代码中使用它?否。
所以最后,你应该做
in create_tuples a b
否。 4 强>
您应该使用<>
来检查不平等。
完整的细化/更正代码
exception Non_equal_list_length
let zip a b =
if List.length a <> List.length b then raise Non_equal_list_length
else
let rec create_tuples a b =
if List.length a = 0 && List.length b = 0 then []
else (List.hd a, List.hd b)::(create_tuples (List.tl a) (List.tl b))
in
create_tuples a b
进一步改进:
最终改进的代码:
exception Non_equal_list_length
let zip a b =
let rec zipping acc = function
| [], [] -> List.rev acc
| hd1::tl1, hd2::tl2 -> zipping ((hd1,hd2)::acc) (tl1,tl2)
| _ -> raise Non_equal_list_length
in
zipping [] (a,b)
答案 1 :(得分:1)
表达式let a = b
仅在模块的最顶层有效,它定义了从模块导出的名称。在其他任何地方,此表达式用于引入局部变量(或变量),其形式为let a = b in c
。您错过了in
关键字以及您希望使用本地变量create_tuples
的表达式。
(按顺序获取语法时会发现一些其他错误。)
<强>更新强>
这是一个使用用let a = b in c
声明的辅助函数的函数的简单示例:
let myrev l =
let rec irev sofar = function
| [] -> sofar
| hd :: tl -> irev (hd :: sofar) tl
in
irev [] l