The function run_counter
may create m threads, each counting from 0 to n:
let run_counters m n =
let rec count x =
if x > n then ()
else ( Printf.printf "%d" x;
Thread.yield ();
count (x 1) )
in
Thread.create count 0
However I don't know how to create multiple Threads, I tried to write a recursive call with a counter m but I get an Error:This expression has type t but an expression was expected of type unit
let run_counters m n =
let rec count x =
if x > n then ()
else ( Printf.printf "%d" x;
Thread.yield ();
count (x 1) )
in
let rec inc n =
if n = 0 then () else
inc (n-1);
Thread.create count 0;
CodePudding user response:
Ok so your function is a bit of mess, first there is a syntax error:
let run_counters m n =
let rec count x =
if x > n then ()
else ( Printf.printf "%d" x;
Thread.yield ();
count (x 1) )
in
let rec inc n =
if n = 0 then () else
>>>>> inc (n-1);
Thread.create count 0;
At location >>>>>
, there is a let rec inc...
without an in ...
following it, you just interrupt the expression with a semicolon. If we replace it with in
, then the function inc
is reported as being unused.
Let's take a step back for a minute, and write each functions separately, this will become a lot easier than trying to do everything at once. Also, you can test individual functions more easily.
Do something n
times
First, write a function that calls some function f
for its side-effects, n
times. We could write a recursive version (and if that's homework, you probably are asked to do that), but OCaml has for loops so let's use them:
let rec call_n_times f n =
for i = 0 to (n-1) do
f i
done
For example, this prints number from 0 to 2, and returns nothing (unit type):
# call_n_times (fun n -> Printf.printf "%d\n" n) 3;;
0
1
2
- : unit = ()
In fact, this example is what your threads are supposed to do (what a coincidence).
Print increasing numbers
In our future tests we will be calling different counters, so let's add a parameter that is the name of the counter:
# let print_n name = call_n_times (fun i -> Printf.printf "%s %d\n" name i);;
val print_n : string -> int -> unit = <fun>
As you can see, we name print_n
the partial application of call_n_times
with a function, the remaining argument n
is implicit here.
# print_n "test" 3;;
test: 0
test: 1
test: 2
Spawn 1 thread
The next step is writing a function that just spawns one thread, and ask it to execute print_n
(so it needs an integer argument) with the name of the thread.
Using partial application as previously, this is:
# let spawn_counter name = Thread.create (print_n name);;
val spawn_counter : string -> int -> Thread.t = <fun>
For example:
# spawn_counter "single-thread" 3;;
- : Thread.t = <abstr>
# Thread.yield();;
single-thread: 0
single-thread: 1
single-thread: 2
- : unit = ()
Name a thread from a number
We need also an intermediate function that produces a name (a string) from a number, let's quickly write that:
# let thread_name = Printf.sprintf "<thread %d>";;
val thread_name : int -> string = <fun>
Spawn m
threads
Now we can write spawn_m_n_counters
:
# let spawn_m_n_counters m n =
call_n_times (fun i -> spawn_counter (thread_name i) n) m;;
val spawn_m_n_counters : int -> int -> unit = <fun>
# spawn_m_n_counters 3 5;;
- : unit = ()
Refactor
You have a basic skeleton of your functions, but I left Thread.yield()
out of the functions.
Also, you want to collect all the spawn threads so that you can join
them. That means you need a call_n_times
that collects the output of the function. See if you can write that recursively.