Thursday, September 16, 2010

I want a "slide" operator

I've been writing imperative code for a long time and I noticed that I often extract a value from a variable, then change the variable immediately afterward. This is evident in numerous iterative algorithms, such as the fibonnaci algorithm:
int a = 0, b = 1, tmp;
for(;;) {
tmp = b;
b = a + b;
a = tmp;
Notice how "a" gets the old value of b, and "b" gets the old value of a + b.

Another pattern is that you want to do something the first time some code is reached:
if (!initialized) {
initialized = true;
Again, we read the value of the variable and then change it.

What if the user clicks a column on a ListView, then clicks a second column? Then the list should be sorted first by the second column, then by the column that was clicked earlier. I wrote some code for this earlier today:
public void SortByColumn(int column)
if (_primarySortColumn == column) {
_secondarySortAscending = !_secondarySortAscending;
_primarySortAscending = !_primarySortAscending;
} else {
_secondarySortColumn = _primarySortColumn;
_secondarySortAscending = _primarySortAscending;
_primarySortColumn = column;
_primarySortAscending = true;
Here, the pattern occurs in the "else" clause.

Since this pattern happens so much, I think there should be an operator for it, let's say "<-". A natural name for it would be the "shift" operator, but I'll call it the "slide" operator or maybe the "rotate" operator, to distinguish it from the bitwise left shift "<<". Using this operator, fibonnaci becomes
int a = 0, b = 1;
for(;;) {
a <- b <- a + b;
The operator is the same as the assignment operator, except that the result of the expression is the old value of the left-hand side, not the new value. So "a <- b <- a + b" is equivalent to "a <- (b <- a + b)", which is equivalent to "temp = b, b = a + b, a = temp". Note that "a <- b <- a + b" is also equivalent to "a = b <- a + b"; since the old value of "a" is discarded, it doesn't matter whether we use "=" or "<-" to change it.

The initialization code could be expressed more briefly with the slide operator:
if (!(initialized <- true))
And similarly for the sorting code:
_secondarySortColumn <- _primarySortColumn <- column;
_secondarySortAscending <- primarySortAscending <- true;

The semantics of the slide operator imply creation of a temporary variable, but probably in some cases the temporary can be eliminated if the compiler can determine that the order of operations doesn't matter, or that the temporary variable isn't being used.

The operator could also be used for swapping values:
a <- b <- a

A second temporary variable is needed in case the left-hand side is expensive or has side-effects, in which case it should only be evaluated once. For example, if the code is
savedValue <- GetActiveItem().Value <- savedValue
then GetActiveItem() shouldn't be called twice, so another temporary must be introduced (the exact details depend on the programming language):
temp1 = GetActiveItem();
temp2 = temp1.Value;
temp1.Value = savedValue;
savedValue = temp2;
Now when can I get my slide operator in a real language?

No comments: