Rethinking Control Flow

kyleperik.com

Assumptions about Program Structure and Execution

Programs have long been defined by their execution rather than their purpose or problem domain. In recent years, thinking has shifted towards more declarative syntax that is more suited to the specific domain of problems at hand.

Even still, I believe there are other techniques of thinking and programming for different problem spaces that have been left largely unexplored.

Mapping out Control Flow

Control Flow is a term used when describing the path of program execution. While it is necessary, by definition, control flow should be de-emphasized in declarative programming. Yet, I believe micromanaging control flow still plays an active role in even the most functional programs today.

Consider the following pseudo code

function count (text) {
	words = split(text)
	return length(words)
}

result = count('foo bar baz')
log(result)

Now consider the flow of execution.

Simple enough, we just read from top to bottom (jumping as needed). First count is called, which calls split, then length, returning the result, which is given to log to print.

Now slightly a different question, what does the dataflow look like?

'foo bar baz' -> count ( split -> length ) -> log

Looking at this one liner, this feels like a nice way to understand the execution and flow of data, but it doesn't match up exactly with the top-to-bottom layout. So even despite the lack of control flow operations like loops, conditionals or lambdas, it can take effort to extract and understand the data flow.

To further contrast, the simple arrows show the execution pointer moving down, yet the data is jumping all over the place:

control_vs_dataflow.png

For me, when I'm trying to debug some code, the first thing I try to do is to understand where the data is coming from and where is it going. This allows a divide and conquer approach, that ensures O(log(n)) dev time to find the discrepancy.

Flow

There are several ways of avoiding this problem in practice, but today I will recommend checking out a rare paradigm.

The technique is replicated in several domains, but has yet to be unified under a paradigm besides generically "declarative". Some include Functional Reactive Programming, Reactive frontend frameworks, spreadsheets, message passing systems such as Erlang, and service oriented architectures on a more meta level. I'd recommend these systems be unified as sub classes under Flow Based Programming, which has existed since the 1970's (as most ideas in programming have).

What makes this paradigm distinct from most, even other declarative programming paradigms, is it promotes the flow of data to become a first class citizen.

Mapping out Data Flow

Let's consider a more complex example using FBP instead.

mouse/click -> button/check
button/click -> counter/increment
counter/result -> console/log

In this fictional example, we have an interactive environment, where a mouse device provides data about clicks, which are sent to a button to check for a click. Any resulting clicks are sent to a counter to increment. The resulting count over time is sent to the console to log.

Notice now that both control flow and data flow is very clear, moving from left to right, top to bottom. In more complex cases, it can be represented well as a directed graph, like a flow chart. Either way, data flow is explicit, and in doing so, control flow is actually removed. In other words, the program has no control over the flow of the program counter, in fact, it's not obvious that any program counter is necessary in a program like this. All nodes can be operating in parallel.

So what other benefits can this paradigm provide? Spreadsheets provide a glance into what's possible by simply allowing arbitrary references with functions for math and aggregation, which update reactively to arbitrary updates to cells upstream. Propagators and truth resolution systems are another concept along the same lines.

In a generic system where data flow is our key means of abstraction, we can build more flexible and modular systems that are easier to analyze and experiment than much of what's out there today, so give it a try!