The field of compiler construction is often regarded as an old-school topic. “We’re not in the 1960’s anymore” I heard some people say. I don’t agree. Thinking about the structure and translation of programming language can reveal interesting and productive new insights.
Recently I wrote a little interpreter for the AST of an Algol-like language to keep my TDD skills in shape. I wondered which impact Command-Query Separation would have on language interpretation. What happens when CQS is baked in to the language? I came up with little examples like:
val balance = deposits.sum() + withdrawals.sum()
The sum() function is of course free of (abstract) side-effects.When sketching these on object diagrams, I came up with something like this:
locals.assign( locals.resolve("balance"), plus( sum(instance.resolve("deposits")) sum(instance.resolve("withdrawals")) ) )
Doesn’t this look familiar? I grabbed my copy of SICP (“Structure and Interpretation of Computer Programs”) and started reading. Using Scheme / LISP notation the above example looks roughly like this:
(setq (balance) (+ (sum deposits) (sum withdrawals) ) )
Interesting. It means that following the Command-Query Separation prinicple makes you write functional programs as right-hand side of assignment expressions and feature calls. It also means OOP and functional programming have much more in common than just both being Turing-complete.
Functional programmers seem to hate any form of state. Assignment is called “setq” and required production of side-effects like writing to files or reading network input is encapsulated in the hard-to-grasp concepts of Monads. On the other hand, typical Java / OO developers more or less ignore the power of creating immutable computations.
Investigating the common structure reealed how to apply functional programming to real-world systems without the unreadable syntax of LISP – great :-).