Reputation: 1147
I'm writing a function that take a pair of lists, if the length of two lists are equal then create a pair of each element from each list, but my function doesn't work and the compiler say there is a syntax error
Could someone explain why there is a syntax error at the semicolon at the end of my function?
This is my code:
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]);;
Upvotes: 1
Views: 585
Reputation: 25812
There are quite a few possible improvements and errors in your code and I list them all in the following:
No. 1
If you write your code in a file and try to compile / run your file, then you don't need ;;
in the end for every function.
No. 2
let define_tuple a b = (a, b);;
You don't need to define such a function, instead, you can directly use (a, b)
.
No. 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
For your first if ... else ...
, it is not correct as the if
branch returns unit
and else
branch returns list
.
In OCaml, if
and else
or any branch of pattern matching should returns the same type.
3.2
Because of 3.1, I suggest you write an exception for the non-equal lengths
case. In this way, the whole function still returns list and code is more readable and users of your function can also get the chance to "catch" your exception case.
3.3
for function 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
You don't need to use fst (a,b)
, instead, just a
is enough because a is already known.
It is the same for your snd
usage.
Basically you don't need fst
and snd
all over your code.
3.3.1.1
You should check whether a
and b
's lengths are 0 or not, not the tl
of them.
3.3.2
You also don't need (a,b)
a tuple as the parameters for create_tuples
, instead, you can use create_tuples a b
. It is better because your code doesn't need to create a tuple for a pair of parameters.
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)))
First of all, List.append
is to append one list to another list. In your case, you are adding an element to a list, so you should use ::
.
You should use ()
to include a function application if you want the value of the function application to be used.
for example, you should do (define_tuple (List.hd (fst (a, b))) (List.hd (snd (a, b)))):: (create_tuples (List.tl (fst (a, b)), List.tl (snd (a, b))))
.
If you consider the previous points together, you can do
(List.hd a, List.hd b)::(create_tuples (List.tl a) (List.tl b))
3.4
You have defined function create_tuples
, but did you really use it in your code? No.
So at the end, you should do
in create_tuples a b
No. 4
You should use <>
to check inequality.
The full refined/corrected code is
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
Some more improvements:
Final improved code:
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)
Upvotes: 2
Reputation: 66808
The expression let a = b
is valid only at the topmost level of a module, where it defines names to be exported from the module. Everywhere else this expression is used to introduce a local variable (or variables), and it has the form let a = b in c
. You're missing the in
keyword, and the expression in which you want to use your local variable create_tuples
.
(There are some other errors that you will find when you get the syntax in order.)
Update
Here's a simple example of a function that uses a helper function declared with let a = b in c
:
let myrev l =
let rec irev sofar = function
| [] -> sofar
| hd :: tl -> irev (hd :: sofar) tl
in
irev [] l
Upvotes: 1