Julia has a built-in system for running tasks, which are, in general, known as coroutines. With this, a computation that generates values (with a produce
function) can be suspended as a task, while a consumer task can pick up the values (with a consume
function). This is similar to the yield
keyword in Python.
As a concrete example, let's take a look at a fib_producer
function that calculates the first n Fibonacci numbers (refer to the Recursive functions section in Chapter 3, Functions), but it doesn't return the numbers, it produces them:
# code in Chapter 4\tasks.jl
function fib_producer(n)
a, b = (0, 1)
for i = 1:n
produce(b)
a, b = (b, a + b)
end
end
If you call this function as fib_producer(5)
, it waits indefinitely. Instead you have to envelop it as a task that takes a function with no arguments:
tsk1 = Task( () -> fib_producer(10) )
This gives the following output as Task (runnable) @0x0000000005696180
. The tasks' state is runnable. To get the Fibonacci...