I wrote about it here, you’ll find a concrete example. See also the blog posts from Nathaniel J Smith, esp. this one for a good explanation of the pitfalls associated with traditional imperative concurrency.
Maintaining a hierarchy of running processes has several benefits :
- when a process fails it can propagate the exception to its parent
- when a parent process detects a failing child it can make an appropriate decision such as cancelling the siblings
- the lifetime of child processes are enclosed by their parent, so resources allocated by children are guaranteed to be freed when the parent terminates
Now, when a process is forked with an imperative construct (e.g with future
, go
), it doesn’t know which one is its parent. You have to program defensively, and implement your own error handling and cancellation support. You may end up building a supervisor hierarchy by hand.
In contrast, in functional style, logical processes are values. If a process is defined as a composition of other processes, the parent-child relationship is made explicit by construction. When the process is ultimately spawned, the process data structure is naturally materialized into a supervisor hierarchy.