The Economics of Semantic Coding
The power of text-based editing in coding is that no time is wasted communicating semantics to the editor. Editing is a simple stream of character additions, deletions, and replacements; semantics are not required. This makes efficiency one-to-one with keystrokes. The work of any operation is simply the sum of its keystrokes.
Structured editing offers a different economy. The price of communicating semantics is paid up front, and then a (typically small) number of keystrokes communicates enough to make the semantics manifest.
Expressions involving few characters but complicated semantics typically make these economics unappealing. Consider x+1, an expression with very few characters requiring very few keystrokes in a text-based environment. But the semantics aren’t as simple:
call the+function on the local referencexand the constant value1
Expressions of this sort do not make a compelling case for structured editing. The cost of communicating semantics seems inordinate compared with the minimal characters necessary to form the expression. In fact, this situation feels viscerally frustrating: “This is the simplest statement I’ll ever code and it feels so cumbersome!”
But it would be incorrect to assume that the economics of structured editing scale proportionally from these sorts of simple expressions. In fact, they move in the opposite direction: as editing moves to more complicated refactoring commands the complexity of the semantics stays constant while the keystrokes and boilerplate become much more tedious.
Imagine you’ve written a simple expression that you later realized should be abstracted into its own function. Perhaps you anticipate this logic being broadly applicable, so your ideal refactoring is to build a new function around the expression and then immediately call it.
For example, you might want to transform something like this:
g(x) ? 0 : h(x, y)
into something like this:
def f(x, y) = { g(x) ? 0 : h(x, y) }
f(x, y)Despite the numerous keystrokes and tedious boilerplate of this refactoring, the semantics are quite straight-forward:
Make this expression a function calledfthen refactor expression as callf
It’s commands like these where the upfront cost of communicating intent begins to outweigh the subsequent cost of keystrokes. This is a trade-off commonly leveraged by various editing paradigms.
Autocomplete features can be seen as a step along this economic spectrum. By engaging the autocomplete dialog, you communicate the semantics of your intent (i.e., “I want to reference a defined entity”), and in exchange for this up front cost you spend fewer characters to achieve your edit.
Similarly, modal editing (such as in VIM) offers this same trade-off: use a keystroke to communicate a semantic context and your next keystrokes become more valuable.
Here at the isomorƒ project we see structured editing as a way to push much further along this spectrum of editing economics, and we continue to experiment with this paradigm in our quest to improve the coding experience. Beyond the semantic benefits already reaped by the existing rename, clone, and match commands, we’ve recently rolled out some new semantic commands that demonstrate some of this potential:
Refactoring Expressions as Functions
As discussed above, it is commonplace to write an expression and realize that the logic represented might be useful elsewhere. Creating a function that expresses the logic and refactoring the expression as a call to this new function offers benefits in reuse, maintenance, and adaptability. The refactor as function command transforms any expression into a function (after being supplied the new function’s name):


Refactoring Expressions as Values
Whether simply for clarity or perhaps to avoid redundant declarations, it is often useful to transfer an expression to a value declaration and then make use of that value (perhaps repeatedly). The refactor as value command refactors any expression (or multiple identical expressions) into a value declaration and then replaces the expression(s) with a reference to the value.


Refactoring Expressions as Functions Parameters
Another similar pattern for creating value through abstraction is realizing that an expression or reference within a function could be abstracted as an input to the function. The refactor as parameter command takes any expression and adds a parameter to the containing function matching the type of the selected expression. The expression is replaced by the new parameter, and the argument list of any calls to the function is appended with the expression.


Enumerating Constructor Patterns
Adding a basic match statement in isomorƒ will always enumerate the relevant constructor patterns (when types are known and patterns are enumerable), but this is not performed recursively. To enumerate nested sub-patterns, use the enumerate constructor patterns command and create the desired depth of constructor matching.


Branching a Function
Often when applying an existing function, it becomes clear that the behavior of the function isn’t exactly as desired and a slightly altered version will be necessary. Executing the branch command on any function application creates a local copy of the function being called and refactors the application to call the new local version.


De-normalizing a Local Function
As a function evolves the situation can emerge wherein efforts to abstract have gone too far and created indirection where no benefit is conferred. Perhaps a value statement was created with the expectation of multiple usages, but only a single usage materialized. Perhaps a function was envisioned that ended up containing only a trivial transformation not worthy of its own declaration. The refactor-as-expression command takes any local function or value and replaces references to it with the underlying expression, cleanly undoing its declaration.


We have a live sandbox on isomorf.io where you can play around with these commands. Let us know what you think (and if there are other commands or features you’d like to see). Reach out via email, twitter, or our forum.