Can someone explain the syntax used for when you have nested functions?
For example I have a outer and an inner recursive function.
let rec func1 list = match list with
[] -> []
|(head::tail) ->
let rec func2 list2 = match list2 with
...
;;
I have spent all day trying to figure this out and I'm getting a ever tiring "Syntax error".
You don't show enough code for the error to be obvious.
Here is a working example:
# let f x =
let g y = y * 5 in
g (x + 1);;
val f : int -> int = <fun>
# f 14;;
- : int = 75
Update
Something that might help until you're used to OCaml syntax is to use lots of extra parentheses:
let rec f y x =
match x with
| h :: t -> (
let incr v = if h = y then 1 + v else v in
incr (f y t)
)
| _ -> (
0
)
It's particularly hard to nest one match inside another without doing this sort of thing. This may be your actual problem rather than nested functions.
Related
When declaring a function, I've 3 different ways:
let f x = ...
let f = (fun x -> ...)
let f = function
| ... -> (pattern matching)
It's this last one that I don't fully understand how it works.
I was doing a function that, considering a list (we'll assume it has integers in it but could be anything), reverses it, pretty basic, but with a complexity of O(n). After struggling for an hour at least I check the answer, and it is written like this:
let reverse lst =
let rec aux acc = function
| [] -> acc
| hd :: tl -> aux (hd :: acc) tl
in
aux [] lst
I thought that using the key word function was just another way of doing patter matching, but when I do this:
let reverse lst =
let rec aux acc =
match aux with
| [] -> acc
| hd :: tl -> aux (hd :: acc) tl
in
aux [] lst
It doesn't work, and idk why. On top of that, why can we add tl at the end of the first function? Isn't aux a single argument function?
There are a few problems with this question. First, the code you give as the solution for reverse is not valid OCaml. It matches aux (which is a function) against list patterns. Most likely aux was supposed to be acc. But even so it doesn't seem right because it should have two arguments (the accumulated result and the input that still needs to be processed).
Second, your two code examples are the same. You seem to be saying that one works and one doesn't work. That doesn't make sense since they're the same.
IMHO you need to rewrite the question if you want to get a helpful answer.
Ocaml uses currying, which means that a two-argument function is the same thing that a function whose return value is a function.
To define a two-argument function, you can combine all the ways you know of creating one-argument functions:
let f x y = x + y
let f x = (fun y -> x + y)
let f x = function
| y -> x + y
let f = (fun x -> (fun y -> x + y))
let f = function
| x -> function
| y -> x + y
let f x = (let g y = x + y in g)
etc, etc.
All these definitions for f lead to the same result:
val f : int -> int -> int = <fun>
# f 3 4;;
- : int = 7
Note that the signature of f is:
val f : int -> int -> int = <fun>
If we added parentheses to better understand this signature, it would be this:
val f : int -> (int -> int) = <fun>
Meaning that f is a one-argument function whose return value is a one-argument function whose return value is an int.
Indeed, if we partially apply f:
# f 3;;
- : int -> int = <fun>
# let add_three = f 3;;
val add_three : int -> int = <fun>
# add_three 4;;
- : int = 7
The code you give at the end of your question is wrong. It's most likely intended to be this:
let reverse lst =
let rec aux acc l =
match l with
| [] -> acc
| hd :: tl -> aux (hd :: acc) tl
in
aux [] lst;;
val reverse : 'a list -> 'a list = <fun>
# reverse [1;2;3;4;5];;
- : int list = [5; 4; 3; 2; 1]
Locked. There are disputes about this question’s content being resolved at this time. It is not currently accepting new answers or interactions.
I have a problem on my program, when I call on the Ocaml terminal "#matrix81 cache;;" it gives me the error: "This expression has type cache list but is here used with type cache list"
This is my code. Any help?
let rec makeLine w =
let y = w - 1 in
if w <> 0 then 0::(makeLine y)
else []
;;
let rec makeMatrix w h =
let y = h - 1 in
if h <> 0 then (makeLine w)::(makeMatrix w y)
else []
;;
let rec checkCache lc d t =
match lc with
[] -> 0
|x::xs -> if (x.difficulty = d) && (x.terrain = t) then (checkCache xs d t) + 1
else (checkCache xs d t)
;;
let rec checkLine lc d t line =
match line with
[]->[]
|x::xs -> let nt = t +. 0.5 in
let v = 5.0 in
if (nt < v) then
let nx = (checkCache lc d t) in
(nx)::(checkLine lc d nt xs)
else []
;;
let rec matrix81Aux m d lc =
match m with
[] -> []
|x::xs -> let nd = d +. 0.5 in
let v = 5.0 in
if (nd < v) then
(checkLine lc d 1.0 x)::(matrix81Aux xs nd lc)
else []
;;
let matrix81 lc =
let m = makeMatrix 9 9 in
matrix81Aux m 1.0 lc
;;
You don't show the definition of the type cache (or give the line number for the error).
The most common cause of this strange type of error message is that you have defined the same type name twice. This often happens when working from the toplevel and loading files with #use.
It's also possible you're defining the name cache twice some other way.
Recent versions of OCaml add an integer to the type name, to (try to) clarify that two different types are involved:
# type cache = A | B;;
type cache = A | B
# let f = function A -> 3 | B -> 4;;
val f : cache -> int = <fun>
# type cache = C | D;;
type cache = C | D
# let g x = match x with C -> f x | D -> 14;;
Error: This expression has type cache/1023
but an expression was expected of type cache/1018
I just looking for a little advice, how to rewrite code using tail recursion
open Core.Std;;
let rec dig x =
match x with
| 0 -> []
| _ -> x :: dig (x - 1)
;;
let () =
let numbers = dig 10 in
List.iter ~f:(Printf.printf "%d, ") numbers;
Printf.printf "\n";
;;
Any advice will be helpful
let dig x =
let rec f x s =
match x with
| 0 -> s
| _ -> f (x-1) (x::s)
f x []
Is this what you want? It's using tail recursion.
Edit:
for a decreasing seq, just replace (x::s) with (List.append s [x]) or (s # [x]) but it's NOT a good idea,and List.rev is better:
let dig x =
let rec f x s =
match x with
| 0 -> s
| _ -> f (x-1) (s # [x])
f x []
let dig x =
let rec f s z =
if z = x then s
else f (z::s) (z+1)
in
f [] 0
not sure if this floats your boat: You may have to tweak the border cases depending if you want 0 or the starting number included.
If you don't want to use List.rev after building the list backwards (which in my opinion is perfectly fine), nor starting your recursion with 0 instead of n, you can use some kind of continuation:
let dig2 x =
let rec aux x kont =
match x with
| 0 -> kont
| _ -> aux (x-1) (fun l -> kont (x::l))
in
aux x (fun l -> l) [];;
Basically each step returns a function that, given the list built by the remaining steps, will append x to it. We start the recursion with the identity function since we don't have anything to build yet. Then, when we exit from the recursion, we thus just have to apply the empty list to the obtained function.
Well, it seems to can have multiple solutions
open Core.Std;;
let rec digtail ?(l=[]) x =
match x with
| 0 -> l
| _ -> digtail ~l: (l # [x]) (x - 1)
;;
let () =
let numbers = digtail 10 in
List.iter ~f:(Printf.printf "%d, ") numbers;
Printf.printf "\n";
;;
Thanks to all, you helped a lot.
I have a simple code of union-find as below:
let rec find p x =
if p.(x) = x
then x
else
let y = find p (p.(x)) in
p.(x) <- y;
y;;
let union x y p =
p.(find p y) <- p.(find p x);
p
Example:
let a = [|0;1;2;3;4|]
let print_array a =
Array.iter (fun i -> Printf.printf "%i" i; print_string " ") a
let print_union =
let a = union 0 1 a in
print_string "Result union (0, 1): ";
print_array a;
print_string "\n"
the result will be:
Result union (0, 1): 0 0 2 3 4
I am having a hard time to go further to get the disjoint-set.
For instance the example above I want to get: {0,1},{2},{3},{4}
Thank you for your help.
For obvious reasons, you can't print that result without going through the whole structure.
So, you want to collect inhabitants from all of your union-find:
let print_classes a =
(* Let's first create an array for storing the classes *)
let classes = Array.make (Array.length a) [] in
(* Let's now populate it!
I'm going backwards in the array to have nicer printing *)
for i = (Array.length classes) - 1 downto 0
do classes.(a.(i)) <- i :: (classes.(a.(i))) done;
(* And now the printing *)
Array.iter (function
| [] -> ()
| h::t -> Printf.printf "{%d%a}" h
(fun c -> List.iter (fun x -> Printf.fprintf c ",%i" x)) t
)
classes
I used Printf functions for the sake of brevity, you can find their doc here.
Note that this could probably be improved as it creates a potentially big array that may be "almost not" populated. depending on the frequency in which you'll use this function, you may want to store the equivalence class along with the class leader (I had to do that once, I used Set and Map from the stdlib).
i'm trying to learn ocaml right now and wanted to start with a little program, generating all bit-combinations:
["0","0","0"]
["0","0","1"]
["0","1","0"]
... and so on
My idea is the following code:
let rec bitstr length list =
if length = 0 then
list
else begin
bitstr (length-1)("0"::list);
bitstr (length-1)("1"::list);
end;;
But i get the following error:
Warning S: this expression should have type unit.
val bitstr : int -> string list -> string list = <fun>
# bitstr 3 [];;
- : string list = ["1"; "1"; "1"]
I did not understand what to change, can you help me?
Best regards
Philipp
begin foo; bar end executes foo and throws the result away, then it executes bar. Since this makes only sense if foo has side-effects and no meaningful return value ocaml emits a warning if foo has a return value other than unit, since everything else is likely to be a programmer error (i.e. the programmer does not actually intend for the result to be discarded) - as is the case here.
In this case it really does make no sense to calculate the list with "0" and then throw it away. Presumably you want to concatenate the two lists instead. You can do this using the # operator:
let rec bitstr length list =
if length = 0 then
[list]
else
bitstr (length-1)("0"::list) # bitstr (length-1)("1"::list);;
Note that I also made the length = 0 case return [list] instead of just list so the result is a list of lists instead of a flat list.
Although sepp2k's answer is spot on, I would like to add the following alternative (which doesn't match the signature you proposed, but actually does what you want) :
let rec bitstr = function
0 -> [[]]
| n -> let f e = List.map (fun x -> e :: x) and l = bitstr (n-1) in
(f "0" l)#(f "1" l);;
The first difference is that you do not need to pass an empty list to call the function bitsr 2 returns [["0"; "0"]; ["0"; "1"]; ["1"; "0"]; ["1"; "1"]]. Second, it returns a list of ordered binary values. But more importantly, in my opinion, it is closer to the spirit of ocaml.
I like to get other ideas!
So here it is...
let rec gen_x acc e1 e2 n = match n with
| 0 -> acc
| n -> (
let l = List.map (fun x -> e1 :: x) acc in
let r = List.map (fun x -> e2 :: x) acc in
gen_x (l # r) e1 e2 (n - 1)
);;
let rec gen_string = gen_x [[]] "0" "1"
let rec gen_int = gen_x [[]] 0 1
gen_string 2
gen_int 2
Result:
[["0"; "0"]; ["0"; "1"]; ["1"; "0"]; ["1"; "1"]]
[[0; 0]; [0; 1]; [1; 0]; [1; 1]]