I am trying to filter a list of pairs and return a new list containing only the first element of each pair. The input/output should go like this:
input = [('A', 3); ('B', 2); ('D', 1)]
output = ['A'; 'B'; 'D']
The code i have so far is this:
let rec trimList l = function
| [] -> []
| head::tail -> let l' = [fst head] # trimList List.tl l;;
but i get the following error:
Line 3, characters 59-61:
3 | | head::tail -> let l' = [fst (head)] # trimList List.tl l;;
^^
Error: Syntax error
I don't know why this isn't working. I know this is very simple, but i am new to OCaml.
Any help would be appreciated, thank you.
Your syntax problem is caused by the fact that you have let with no corresponding in.
A let expression looks like this:
let v = expr1 in expr2
In essence this establishes a local variable v with value expr1 and has the value of expr2 (which will probably contain instances of the variable v).
You are missing the in part of the let expression.
As another comment, if you define a function like this:
let f l = function ...
You are defining a function of two parameters. There is an implicit parameter defined by the function keyword; the parameter is matched against the following patterns.
Most likely you want to remove the l from you function definition.
There are a few other problems with your code, but I hope this helps to make progress.
Related
Hey everyone I'm new to OCaml and having some problems. So I'm trying to do a recursive function that takes a non-empty list and returns the last element. My list can be any data type though.
Here is what I have right now and it's currently failing on the assertion statement saying "This expression has type int but an expression was expected of type int list.
let rec last l = match l with
[] -> []
|[x] -> [x]
|_::t -> last t ;;
assert(last [1; 2; 3; 4] = 4);;
assert(last ["a"; "b"; "c"; "d"] = "d");;
I often find that a good way to deal with this kind of type errors, is to explicitly annotate the function with the type I want it to have - in this case, I expect that you want the first line to be something like this:
let rec last: 'a list -> 'a = fun l -> match l with
With that, the error changes to:
File "1/hest.ml", line 5, characters 9-10:
5 | |[x] -> [x]
^
Error: This expression has type 'a list
but an expression was expected of type 'a
The type variable 'a occurs inside 'a list
Which is a more helpful error. The problem is, as #PatJ writes in his answer, that as you have written the function you actually return a list with one element (or no elements, when the list is empty), but your usage of the function seems to indicate that you just want the last element.
You can either:
change your usage of the function, so the asserts compare with [4] and ["d"] instead of just the values.
change the function to return Some x and None instead of [x] and [], and change the asserts to assert against Some 1 and Some "d".
change the function to return x instead of [x] and throw an exception in the empty list case - that would be: failwith "empty list"
I think the second solution is the most natural one.
If you go for exceptions, then renaming the function to last_exn would convey to users that they have to beware that the function might throw.
The problem comes from the fact that your function is indeed returning a list, as can be seen in those two lines:
[] -> []
|[x] -> [x]
You want the second line to be |[x] -> x. Of course, you also need to handle the case of an empty list and effectively return something. You can either have it raise an exception, use an option type or have the caller specify a default value.
In this kind of cases, it's better to use an option type:
let rec last_opt l =
match l with
| [] -> None
| [x] -> Some x
| _x::t -> last_opt t
let () =
assert (last_opt [1; 2; 3; 4] = Some 4);
assert (last_opt ["a"; "b"; "c"; "d"] = Some "d"); (* Note that here you could use chars, i.e. 'a', 'b' etc. instead of strings "a", "b" etc. *)
assert (last_opt [] = None)
If you really don't want an option type, you should handle the empty case with care :
let rec last l =
match l with
| [] -> raise (Failure "last")
| [x] -> x
| _x::t -> last t
I am a beginner with OCaml. I would like to skip the first element of my list.
Here is my list:
let l = [1;2;3;4;5;6;7;2;1];;
I want to use this in my FOR:
let l = List.tl l;
here is my full code:
let l = [1;2;3;4;5;6;7;2;1];;
let n = 1;;
let counter = ref 0;;
for i = 0 to (List.length l) do
if List.hd l = n then counter := !counter + 1;
print_int(!counter);
print_string("\n");
let l = List.tl l
done;;
But I have errors in the DONE and it says syntax error.
Can anyone help me please?
Your problem is that let always requires a matching in. The full expression looks like this:
let var = expr1 in expr2
Since you're missing the in part, you get a syntax error.
However, the deeper problem is that you're trying to modify the value of l. The way you have defined l, it's immutable. You can't change its value. If you want to be able to change its value you can define it as a reference, as you have done for counter.
(There is another form of let used at the top level of a module. This form doesn't have a matching in. But your code isn't defining a top-level name, so this is not relevant.)
I have to make a function that takes list a list and returns list of pairs of first and last element,2nd and 2nd last and so forth It doesn't matter if the list has even or odd number of elements because if its odd i will just ignore the middle element.The idea i have is that make a new rec fun that takes old list and its revers as input i think i finished the code but i get Syntax error for ;;
let lip l =
if [] then []
else let l1=l l2=List.rev l in
let rec lp l1 l2 = match l1,l2 with
| [],[] ->[]
| [],h2::t2->[]
| h1::_,h2::_ ->
if (List.length l -2) >= 0 then [(h1,h2)]# lp(List.tl l1) t2
else [] ;;
There are quite a few errors in your code.
I think the specific error you're seeing is caused by the fact that there is no in after let rec lp ....
Every let that's not at the top level of a module needs to be followed by in. One way to think of it is that it's a way of declaring a local variable for use in the expression that appears after in. But you need to have the in expr.
Another way to look at it is that you're defining a function named lp but you're not calling it anywhere.
As #lambda.xy.x points out, you can't say if [] then ... because [] isn't of type bool. And you can't say let x = e1 y = e2 in .... The correct form for this is let x = e1 in let y = e2 in ...
(Or you can write let x, y = e1, e2 in ..., which looks nicer for defining two similar variables to two similar values.)
The following code should at least compile:
let lip list1 =
if list1 = [] then []
else
let list2=List.rev list1 in
let rec lp l1 l2 = match l1,l2 with
| [], [] ->[]
| [], _::_->[]
| h1::_::_, h2::t2 -> (* l1 length >= 2*)
(h1,h2) :: lp(List.tl l1) t2
| h1::_,h2::t2 -> (* l1 length = 1 *)
[]
in
[]
I have made the following changes:
renamed the arguments of lip to make clear they are different from the arguments of lp
removed the alias let l1 = l
changed the if condition to a term of type boolean -- there's not much to compare, so I assume you are checking list1
replaced the list length condition by a pattern match against two heads
the else path is the second match - it might be better to rewrite that one to | [h1, _] -> ...
the definition of lp needs to be followed with the actual body of lip - to make it compile, we just return [] at the moment but you probably would like something else there
As #Jeffrey Scofield already mentioned, you are not using lp in your code. It could help if you added a comment that explains what you'd like to achieve and what the intended role of lp is.
I have a list composed by several couples of numbers:
[(1,2);(3,4);(5,6);(7,8)]
I want to remove the the first element (the head) from the list, so the output should be:
[(3,4);(5,6);(7,8)]
Someone can help me? I was thinking about this function but it doesn't work:
let cut x = function
[] -> []
| (a,b) -> []
| (a,b)::ris -> ris
Just remember, that
let f x y = function -> <code>
is really a shortcut (or a syntactic sugar), for:
let f x y z = match z with -> <code>
So, it just cuts the last argument in a function, and automatically matches on it.
Also, when you pattern matching keep in mind, that all expressions in the left side of pattern match should have the same type. Otherwise, compiler may pick a random one, and decide, that all others have the same type, yielding a somewhat confusing error message. The same is true for the right sides of patter match. So, when you see a compiler message, saying that something is not what he has expected, just check this preconditions:
| [] (* is a list, by definition *)
| (a,b) -> [] (* is a pair, by definition of a pair *)
| (a,b)::ris -> ris (* is a list, by definition of (::) *)
If left part works, look at the right.
Also, if you have a variable that you do not need to use, then you should better give it a name starting with underscore, or just an underscore.
let cut = function
| [] -> []
| _::xs -> xs
You are almost there:
let tl x = match x with
| [] -> [] (* or failwith "empty" *)
| ab::ris -> ris
Few points:
function takes another argument. Your function already get one arg, so use match x with instead.
You are interested only in the list is empty or has a "tail", so you need not pattern-match its element as a tuple.
This function is called "tail", in OCaml, known as List.tl.
You could write simple:
let cut = List.tl
You have little mistake.
Third line should look like
| [(a,b)] -> []
or
| (a,b) :: [] -> []
P.S. by the way, this third line is unnecessary. Just remove it.
And delete x in first line:
let cut = function
I'm writing an interactive calculator in OCaml with some simple commands. Users should be able, among other things, to define their own simple functions (mathematical functions), for instance
let f(x) = x
let g(x) = 2*f(x)
Now, the functions should be handled like in functional languages, that means they should remember their time-of-creation environment. That means, that with a function I have to keep a closure of its environment, which is functions and variables.
I keep currently defined functions in a list of tuples formed like (functions_present_at_the_time_of_creation, variables_present_at_the_time_of_creation, function_name, function_argument_names, function_formula). When I try to add a new function to the list of functions (let's assume, that it's not currently defined and I don't have to overwrite anything), I recurrently iterate to the end of the list of functions and there would like to add a new tuple.
The problem is, assuming my current functions list is of type (a*b*c*d*e) list when i try to add a tuple with itself to the end of it, it changes its type to ((a*b*c*d*e) list*f*g*h*i) list. What can I do to be able to perform such addition of a list to itself, encapsulated in a tuple?
Here's some simple SSCCE I wrote while trying to find a workaround to this issue.
let rec add_to_end list list_copy dummy = match list with
| [] -> [(list_copy, dummy)]
| h::t -> h::(add_to_end t list_copy dummy)
let add list dummy = add_to_end list list dummy
This one tries to do it with a copy of the list. The following one is written without using of a copy (both of these examples don't work, of course):
let rec add_to_end list dummy = match list with
| [] -> [(list, dummy)]
| h::t -> h::(add_to_end t dummy)
The first example doesn't work when trying to use the function add, but when doing it for instance this way (in the interpreter):
let l = [];;
let l = add_to_end l l 1;;
let l = add_to_end l l 2;;
let l = add_to_end l l 3;;
Then it works fine. I'd appreciate any help, I may think about changing the design also, any proposals are very welcome.
Edit: Here's the output of the above commands:
# let l = [];;
val l : 'a list = []
# let l = add_to_end l l 1;;
val l : ('a list * int) list = [([], 1)]
# let l = add_to_end l l 2;;
val l : (('a list * int) list * int) list = [([], 1); ([([], 1)], 2)]
# let l = add_to_end l l 3;;
val l : ((('a list * int) list * int) list * int) list =
[([], 1); ([([], 1)], 2); ([([], 1); ([([], 1)], 2)], 3)]
It's hard to tell whether you're aware that OCaml lists are immutable. You can't add a value to the end of an existing list. An existing list can never be changed. You can create a new list with a value added to the end. If you do this, I don't see why you would want to add a pair to the end consisting of the list and the new value. I suspect you're thinking about it wrong. Here's a function that takes a list and an integer and adds the integer to the end of the list.
# let rec addi i list =
match list with
| [] -> [i]
| h :: t -> h :: addi i t
;;
val addi : 'a -> 'a list -> 'a list = <fun>
# let x = [1;2;3];;
val x : int list = [1; 2; 3]
# addi 4 x;;
- : int list = [1; 2; 3; 4]
# x;;
- : int list = [1; 2; 3]
#
The function returns a new list with the value added to the end. The original list isn't changed.
As a side comment, it's much more idiomatic to add values to the front of a list. Repeatedly adding to the end of the list is slow--it gives quadratic behavior. If you want the other order, the usual thing to do is add everything to the front and then reverse the list--this is still linear.
Edit
Apparently you really want a function that looks something like this:
let f a list = list # [(list, a)]
This is not realistically possible, the types don't work out right. A list can contain things of only one type. So you can conclude that the type of the list t is the same as the type (t, v) list, where v is the type of a. This is a recursive type, not something you would really want to be working with (IMHO).
You can actually get this type in OCaml using -rectypes:
$ ocaml -rectypes
OCaml version 4.00.0
# let f a list = list # [(list, a)];;
val f : 'a -> (('b * 'a as 'c) list as 'b) -> 'c list = <fun>
#
But (as I say) it's something I would avoid.
Edit 2
Now that I look at it, your first code sample avoids requiring a recursive type because you
specify two different copies of the list. Until you call the function with the same list, these are potentially different types. So the function type is not recursive. When you call with two copies of the same list, you create a new value with a type that's different than the type of the list. It only works because you're using the same name l for different values (with different types). It won't work in a real program, where you'd need a single type representing your list.
As another side comment: the beauty of adding values to the beginning of a list is that the old value of the list is still there. It's the tail of the new list. This seems lot closer to what you might actually want to do.