Thursday, January 15, 2009

Little accomplishments

It's great when I get to put new things I've learned to work, especially when it's to the greater good.

Case in point - did you know that assignment operations return the result of the assignment? I didn't until recently - it's one of those obscure language bits that almost never come up, but when they do they can really make life easier.

I'm working on my workflow idea (see my previous post for details) - in particular, I'm toying with the idea of composing workflows from sub-workflows - and so I wrote a workflow that takes two workflows and interleaves their workitems together. At first I used a 'Zip' method which does the job, but if there are more workitems in one workflow than the other, the extras are truncated - this is not what I wanted; I want the extra workitems returned correctly.

So I wrote this Workflow() method, which does the job:

do {

    if (enum1.MoveNext()) {

        yield return enum1.Current;

    } else {

        enum1Done = true;

    }

 

    if (enum2.MoveNext()) {

        yield return enum2.Current;

    } else {

        enum2Done = true;

    }

} while (!(enum1Done && enum2Done));

Interleaving workflow that yields extras

It works, but is verbose and ugly. It is very much imperative code - the *how* of the code obscures much of the *what* and the *why*.

Obscure language features come to the rescue, however, when a little light-bulb goes off in my head. Because assignment operators return the result of the assignment, I can combine the assignment and the test in one statement. The original code becomes this:

var enum1Alive = false;

var enum2Alive = false;

while ((enum1Alive = enum1.MoveNext()) | (enum2Alive = enum2.MoveNext())) {

    if (enum1Alive) yield return enum1.Current;

    if (enum2Alive) yield return enum2.Current;

}

From 14 LOC to 6 - good stuff

This may seem like child's play to some of you, and you're probably right, but for me, this represents an accomplishment (albeit small) in my understanding of the language I use.

1 comment:

andydent said...

Assignments in conditional expressions is discouraged and should at least have a comment saying it is intentional. Many linting programs and some compilers will warn against them.

The reason is simple - if you accidentally type a single = when you meant to use an equality test double == you will have a valid assignment.

One pattern people use to force compilation errors if they make this typo is to reverse the order of comparison, when comparing with a literal, eg:

if (3 = x)...