This kind of expression is not allowed as right-hand side of `let rec' - ocaml

I'm implementing the Raft protocol and my code is as follows:
let rec request_vote_loop: int =
match myState.myRole with
| Follower -> 0
| Leader -> 1
| Candidate ->
let trigger = Domain.spawn(fun _ -> Chan.send c TriggerEvent) in
let request_vote_daemon = Domain.spawn(fun _ ->
let rec loop n =
if n = 0 then 0
else let msg = Chan.recv votes in
match msg with
| (status, id) ->
Domain.join (Array.get !arr id);
if status = 1 then (Array.get votePeers id) := true; (Chan.send c ReceiveVoteEvent); loop (n - 1)
in loop ((Array.length (!peers)) / 2 + 1 - !current_vote)) in
let evt = Chan.recv c in
match evt with
| TimeoutEvent -> myState.myRole <- Follower; 3
| AppendEntriesEvent(_) ->
myState.myRole <- Follower; 4
| ReceiveVoteEvent ->
if !current_vote > (Array.length (!peers) / 2) then
begin current_vote := !current_vote + 1; myState.myRole <- Leader; 3 end
else current_vote := !current_vote + 1; request_vote_loop
| TriggerEvent ->
arr := Array.make (Array.length (!peers)) (Domain.spawn (fun i ->
if (!(Array.get votePeers i)) then 0
else
let conn = Array.get !peers i in
Lwt_main.run
(let+ resp = call_server conn
(RequestVoteArg({
candidateNumber = myState.myPersistentState.id;
term = myState.myPersistentState.currentTerm;
lastlogIndex = (Array.get myState.myPersistentState.logs ((Array.length myState.myPersistentState.logs) - 1)).index;
lastlogTerm = (Array.get myState.myPersistentState.logs ((Array.length myState.myPersistentState.logs) - 1)).term
})) in (match resp with
| Error(s) -> Chan.send votes (0, i); Printf.printf "requestVote: connection failed: %s" s; 1
| Ok(repl, s) ->
(match repl with
| RequestVoteRet(repl) ->
if repl.voteGranted then begin Chan.send votes (1, i); Printf.printf "requestVote: status: %s, currentVote: %d" s !current_vote; 2 end
else
if not (repl.term = (-1l)) then begin myState.myPersistentState.currentTerm <- repl.term; Chan.send votes (0, i);
Printf.printf "requestVote failed because of term: status: %s, currentVote: %d" s !current_vote; 3 end
else Chan.send votes (0, i); Printf.printf "requestVote failed: status: %s" s; 4
| _ -> failwith "Should not reach here" ))))); request_vote_loop
| _ -> failwith "Should not reach here"
in print_endline (Int.to_string request_vote_loop)
But there's an error that "This kind of expression is not allowed as right-hand side of `let rec'", it said my function is of type unit. I don't know what happened...
Thanks in advance.

Your definition starts like this:
let rec request_vote_loop: int = ...
This doesn't define a function, it defines a simple value of type int. The reason is that there are no parameters given.
There's too much code to process (and furthermore it's not self-contained). But I suspect you want to define a function that doesn't take any parameters. The way to do this is to pass () (known as unit) as the parameter:
let rec request_vote_loop () : int = ...
The recursive calls look like this:
request_vote_loop ()
The final call looks like this:
Int.to_string (request_vote_loop ())

Related

OCaml Reading from file and perform some validation

can you help me out, i made this program to get an output from some .txt file like this :
john:3:uk
paul:18:us
#load "str.cma"
let f_test = "/home/test.txt" ;;
(*
Recursive Reading function
*)
let read_lines f_test : string list =
if Sys.file_exists (f_test) then
begin
let ic = open_in f_test in
try
let try_read () =
try Some (input_line ic) with End_of_file -> None in
let rec loop acc = match try_read () with
| Some s -> loop (s :: acc)
| None -> close_in_noerr ic; List.rev acc in
loop []
with e ->
close_in_noerr ic;
[]
end
else
[]
;;
(*Using Records*)
type user =
{
name : string;
age : int;
country : string;
};;
(*
Function to separated info in list
*)
let rec splitinfo ?(sep=":") l = match l with
| [] -> []
| x::xs -> (Str.split (Str.regexp ":") x)::splitinfo xs;;
(*
Function to get users position
*)
let get_user l:user =
let age = int_of_string (List.nth l 1) in
let user_name = List.nth l 0 in
{
name = user_name;
age = age ;
country = List.nth l 2;
};;
(*
Function to check some parameter is valid
*)
let par1 u: int =
if (u.age = 3) then
1
else
0;;
(*
Reporting function
*)
let report_statistics list_users =
let child = ref 0 in
let teenager = ref 0 in
let adult = ref 0 in print_string (" ----- -- Stats -- ----- \n" ) ;
List.iter (
fun user_l -> (
match user_l with
| [] -> print_string("> no user <\n")
| _ ->
let user = get_user user_l in
if (par1 user = 1) then (
print_string (" "^ user.name ^" --> Child \n" ) ;
child := !child + 1;
)
else
print_string (" "^ user.name ^" --> Other \n" );
)
) list_users;
print_string ("------- List ---- ");
print_newline();
print_string ("Child " );
print_int(!child);
print_newline();
print_string ("Teenager ") ;
print_int(!teenager);
print_newline();
print_string ("Adult ");
print_int(!adult);
print_newline();
;;
The program compile but doesn't output any result ...
What am i missing ?
I kept the function to check parameters simple so i can understand it better but can't figure it out why it isn't outputing any result
Can you help me out here ?
Thanks in advance :)
The code as given defines some functions such as read_lines and report_statistics. But there are no calls to these functions.
If there is no other OCaml source involved, this is probably your problem. You need to call the functions.
It is fairly customary to have a "main" function that does the work of an OCaml program, and then (this is key) you have to actually call the main function:
let main () =
(* Call the functions that do the work of the program *)
let () = main ()
I have many times forgotten this last line and then nothing happens when I run the program.

Why is this OCaml code resulting in a runtime error?

I am trying to run the following code on a coding question website and it says there is a runtime error, but running it on the top-level ocaml seems to work fine. Could there be any source of error in the code? Thanks in advance
The question is to find the number of 'good segments' within the given list and a specific number. A good segment is defined as follows:
A and B are positive integers such that A < B.
x that satisfies A <= x <= B is not an element of the given list.
The following are the inputs.
n, which is the number of elements in the list that will be given.
a, b, c, ... which are the elements of the list.
t, which is the number that must be included in the segment.
The output should be a single number printed out.
Edited Code:
let rec drop_value l to_drop =
match l with
| [] -> []
| hd :: tl ->
let new_tl = drop_value tl to_drop in
if hd = to_drop then new_tl else hd :: new_tl
;;
let rec find_start li t cur_min =
match li with
| [] -> cur_min
| hd :: tl -> let new_min = abs (t - hd) in
if new_min = 0 then find_start tl t new_min
else if new_min < cur_min && t > hd then find_start tl t new_min
else find_start tl t cur_min
;;
let rec find_end li t cur_min =
match li with
| [] -> cur_min
| hd :: tl -> let new_min = abs (t - hd) in
if new_min = 0 then find_end tl t new_min
else if new_min < cur_min && t < hd then find_end tl t new_min
else find_end tl t cur_min
;;
let rec contains_value l value =
match l with
| [] -> false
| hd :: tl -> if hd = value then true else contains_value tl value
;;
let nums = ref [];;
let n = read_int () in
for i = 1 to n do
Scanf.scanf " %d" (fun a ->
nums := a :: !nums)
done;
Scanf.scanf " %d" (fun t ->
if contains_value !nums t then print_int 0
else let start = if List.length !nums = 1 then 1 else abs (find_start !nums t 1001 - t) in
let finish = find_end (drop_value !nums start) t 1001 + t in
if t > start && t < finish then (if start = 1 && List.length ! nums = 1 then print_int ((t - start + 1) * (finish - t) - 1) else print_int ((t - start) * (finish - t) - 1))
else let start = 1 in print_int ((t - start + 1) * (finish - t) - 1))
;;
eg.
5
4 8 13 24 30
10
should give
5
=> [9, 10], [9, 11], [9, 12], [10, 11], [10, 12]
You don't describe the exact input format that your code is going to get. This makes it pretty much impossible to debug your code.
When I compile and run your code (as m.ml) using the input you describe I see this:
$ ./m
5 4 8 13 24 30 10
Fatal error: exception Failure("int_of_string")
In fact no matter what format I try for the input I get the same result.
So that is probably what is happening at the website.
In my experience it always causes more harm than good to use scanf. Combining it with other input functions is probably going to make things worse.
If you describe the expected format of the input carefully, somebody on StackOverflow can recommend a way to get your numbers.
In the meantime here's a way to read all the numbers on one line:
let rec split_at list n =
if n = 0 then
([], list)
else
match list with
| [] -> ([], [])
| h :: t ->
let (a, b) = split_at t (n - 1) in (h :: a, b)
in
let (nums, t) =
let line = read_line () in
let nstrs = Str.split (Str.regexp "[ \t][ \t]*") line in
match List.map int_of_string nstrs with
| [] -> failwith "no numbers"
| n :: rest ->
if List.length rest <> n + 1 then
failwith "bad count"
else
let (nums, tlist) = split_at rest n in
(nums, List.hd tlist)
in
. . .

Build a sequence from a function

I wrote these function to build a sequence from a function i am having a stack overflow error while testing it
let rec from_fun f ()=
match f () with
| None -> Nil
| Some e -> Cons(e, from_fun f)
from_fun (fun () -> let x = 0 in if x<10 then Some (x+1) else None)
thanks
Your function always returns Some 1. It never returns None. So the sequence is infinitely long and the stack overflows while building it.
If you want a function to return different values when you call it, you can do two things. First, you can pass it different parameters. This isn't possible for your design of from_fun--the parameter to the function is always (). Second, your function can be impure. I.e., the function can maintain some mutable state.
Here is an example of a generator:
let range_generator from below step =
let counter = ref from
in fun () ->
if (!counter < below)
then (let result = (Some !counter) in
counter := !counter + step;
result)
else None
For example, a call to range_generator 0 10 2 returns a closure over an internal counter mutable variable which generates all natural even numbers below 10:
# let gen = range_generator 0 10 2;;
val gen : unit -> int option = <fun>
Each call to gen possibly mutates the internal counter:
# gen();;
- : int option = Some 0
# gen();;
- : int option = Some 2
# gen();;
- : int option = Some 4
# gen();;
- : int option = Some 6
# gen();;
- : int option = Some 8
# gen();;
- : int option = None
# gen();;
- : int option = None
With your function:
# from_fun (range_generator 0 5 1);;
- : int list = [0; 1; 2; 3; 4]
The variable x you are using is local to the anonymous function you are using. As a result the function always return Some 1.
What you probably wanted to do is for the function to take an argument:
let rec from_fun f n =
match f n with
| None -> Nil
| Some e -> Cons(e, from_fun f e)
let seq = from_fun (fun x -> if x<10 then Some (x+1) else None) 0
EDIT:
Here is a solution with the appropriate type signature:
let rec from_fun f () =
match f () with
| None -> Nil
| Some e -> Cons(e, from_fun f ())
let x = ref 0
let seq = from_fun
(fun () ->
let v = !x in
if v < 10
then begin
x := v + 1;
Some v
end
else None)
()
It is worth noting that because of the side effects, you would have to reinitialise x before building a new sequence. The unit argument passed in parameter to from_fun is unnecessary, you could remove it.

Generate natural numbers and printing them using 2 communication servers in Concurrent ML

I have a homework where i need to write 2 communication servers, one which generates natural numbers and the other which prints them. the generating server will be sending to the printing server. The servers should communicate over the shared channel chan.The main function should spawn a thread for each server.
`
val sender = fn : int -> unit
val receiver = fn : unit -> 'a
val main = fn : unit -> unit
`
And so far this is code i have written:
`
datatype 'a inflist = NIL
| CONS of 'a * (unit -> 'a inflist);
fun HD (CONS(a,b)) = a
| HD NIL = raise Subscript;
fun TL (CONS(a,b)) = b()
| TL NIL = raise Subscript;
fun NULL NIL = true
| NULL _ = false;
fun TAKE(xs, 0) = []
| TAKE(NIL, n) = raise Subscript
| TAKE(CONS(x,xf), n) = x::TAKE(xf(), n-1);
fun FROMN n = CONS (n,fn () => FROMN (n+1));
val natnumber = FROMN 0;
fun printGenList f (h::t) = (f h; printGenList f t);
fun printList l = printGenList (fn(e) => print(Int.toString(e)^" ")) l;
fun printPairList l = printGenList (fn(e,f) => print("("^Int.toString(e)^", "^Int.toString(f)^") ")) l;
CM.make "$cml/cml.cm";
open CML;
val chan: int chan = channel();
fun gen ch () = send (ch, printList(TAKE(natnumber,101)));
fun printnat ch () = recv (ch);
fun main () =
let
val ch = channel() :int chan ;
val _ = spawn (gen ch);
val _ = spawn (printnat ch);
in
()
end;
`
But i am not getting the output. Am i going wrong in my syntax or the logic?
I am new to SML and Concurrent ML. Please help me.
Why are you using a infinite list? There are simpler ways to implement this.

To convert a a string list list to an string array array in OCaml

I'm trying to get a pretty print function to print the query result of my database in OCaml. I've been following this approach http://mancoosi.org/~abate/ocaml-format-module
I have this code so far:
let pp_cell fmt cell = Format.fprintf fmt "%s" cell;;
let pp_header widths fmt header =
let first_row = Array.map (fun x -> String.make (x + 1) ' ') widths in
Array.iteri (fun j cell ->
Format.pp_set_tab fmt ();
for z=0 to (String.length header.(j)) - 1 do cell.[z] <- header.(j).[z] done;
Format.fprintf fmt "%s" cell
) first_row
let pp_row pp_cell fmt row =
Array.iteri (fun j cell ->
Format.pp_print_tab fmt ();
Format.fprintf fmt "%a" pp_cell cell
) row
let pp_tables pp_row fmt (header,table) =
(* we build with the largest length of each column of the
* table and header *)
let widths = Array.create (Array.length table.(0)) 0 in
Array.iter (fun row ->
Array.iteri (fun j cell ->
widths.(j) <- max (String.length cell) widths.(j)
) row
) table;
Array.iteri (fun j cell ->
widths.(j) <- max (String.length cell) widths.(j)
) header;
(* open the table box *)
Format.pp_open_tbox fmt ();
(* print the header *)
Format.fprintf fmt "%a#\n" (pp_header widths) header;
(* print the table *)
Array.iter (pp_row fmt) table;
(* close the box *)
Format.pp_close_tbox fmt ();
;;
(** Pretty print answer set of a query in format of
* col_name 1 | col_name 2 | col_name 3 |
* result1.1 | result2.1 | result3.1 |
* result1.2 | result2.2 | result3.2 |
* #param col_names provides the names of columns in result outp ut *)
let pretty_print fmt pp_cell (col_names, tuples) =
match col_names with
| [] -> printf "Empty query\n"
| _ ->
printf "Tuples ok\n";
printf "%i tuples with %i fields\n" (List.length tuples) (List.length col_names);
print_endline(String.concat "\t|" col_names);
for i = 1 to List.length col_names do printf "--------" done; print_newline() ;
let print_row = List.iter (printf "%s\t|") in
List.iter (fun r -> print_row r ; print_newline ()) tuples;
for i = 1 to List.length col_names do printf "--------" done; print_newline() ;
let fmt = Format.std_formatter in
Format.fprintf fmt "%a" (pp_tables (pp_row pp_cell)) (Array.of_list col_names,tuples);
flush stdout
;;
let print_res (col_names, tuples) =
let fmt = Format.std_formatter in
pretty_print fmt pp_cell (col_names, tuples)
;;
The problem is in the line
Format.fprintf fmt "%a" (pp_tables (pp_row pp_cell)) (Array.of_list col_names,tuples);
basically because I need tuples to be and string array array (a matrix) while its type is string list list. So I tried to solve it by converting the list list into a matrix following this approach http://www.siteduzero.com/forum-83-589601-p1-ocaml-convertir-un-list-list-en-array-array.html with this code:
let listToMatrix lli =
let result = Array.init 6 (fun _ -> Array.create 7 2)
let rec outer = function
| h :: tl, col ->
let rec inner = function
| h :: tl, row ->
result.[row].[col] <- h
inner (tl, row + 1)
| _ -> ()
inner (h, 6 - List.length h)
outer (tl, col + 1)
| _ -> ()
outer (lli, 0)
result
;;
But I just a syntax error while compiling:
File "src/conn_ops.ml", line 137, characters 2-5:
Error: Syntax error
make: *** [bin/conn_ops.cmo] Error 2
I don't really know what to do, or how I can accomplish the conversation of the list list into the matrix. My approach is the correct? This has been the first time I've worked with OCaml and it's been quite a pain in the *, so please, try to be kind with me :D
This is a lot of code to read in detail, but it looks like you're missing a semicolon after result.[row].[col] <- h. However, this code looks suspicious to me. The notation .[xxx] is for accessing individual characters of a string. You want to use array index notation .(xxx), seems to me.
Here is a function that changes a string list list to a string array array. Maybe it will be useful:
let sll_to_saa sll = Array.of_list (List.map Array.of_list sll)
Actually, this function changes any list of lists to an array of arrays; it doesn't have to be strings.
I'm not sure I understood your entire post, but if you want to convert
a string list list into a string array array, you can do this
quite easily with the Array.of_list function:
# let strings = [["hello"; "world"]; ["foo"; "bar"]];;
val strings : string list list = [["hello"; "world"]; ["foo"; "bar"]]
# Array.of_list (List.map Array.of_list strings);;
- : string array array = [|[|"hello"; "world"|]; [|"foo"; "bar"|]|]
I hope this helped.
Your function is not syntacticly correct. Below is a fixed version:
let listToMatrix lli =
let result = Array.init 6 (fun _ -> Array.create 7 2) in
let rec outer = function
| h :: tl, col ->
let rec inner = function
| h :: tl, row ->
result.(row).(col) <- h;
inner (tl, row + 1)
| _ -> ()
in
inner (h, 6 - List.length h);
outer (tl, col + 1)
| _ -> ()
in
outer (lli, 0);
result
;;
As noted in other answers:
the subscript operators for arrays are parentheses,
some semi-colons are missing,
sometimes you forget to use the keyword in to mark the expression where your definition will be used.
Please note that I didn't check if the function does what it is supposed to do.