Have you ever wrote code similar with?:

boolean first = true;
StringBuilder result = new StringBuilder("");
 
for (Item item : collection) {
  if (!first) {
    result.append(", ");
  } else {
      first = false;
  }
 
  result.append(item);
}

I did, and I more often than not need this kind of code, and, as you do, I also dislike it.

It's ugly, hard to figure out what it does unless you stop a bit to think. This is why on my Germanium project I've picked a different strategy. I've created a class named OnceFirstIterator that contains the full "if first item state in it".

So no more if (first) then blah.

How does the end code look? I believe it's awesome, but you be the judge:

Simple list joining

OnceFirstIterator<String> comma = new OnceFirstIterator<String>("", ", ");
StringBuilder result = new StringBuilder("");
 
for (Item item : collection) {
  result.append(comma.next())
    .append(item);
}

or

Query path processing

OnceFirstIterator<String> parameterJoiner = new OnceFirstIterator<String>("?", "&amp;");
StringBuilder queryPath = new StringBuilder("");
 
for (Item queryItem : queryParameters) {
  result.append(parameterJoiner.next())
    .append(queryItem);
}

or

Basic SQL building

OnceFirstIterator<String> whereKeyword = new OnceFirstIterator<String>(" where ", " and ");
OnceFirstIterator<String> orderByKeyword = new OnceFirstIterator<String>(" order by ", ", ");
StringBuilder sql = new StringBuilder(...);
 
for (WhereClause whereClause : whereClauses) {
  sql.append(whereKeyword.next())
    .append(whereClause);
}
for (OrderByClause orderByClause : orderByClauses) {
  sql.append(orderByKeyword.next())
    .append(orderByClause);
}

So what are you waiting? Here is also a JavaScript implementation:

var onceMany = function(once, many) {
    var firstGenerated = false;
    return {
        next : function() {
            if (firstGenerated) {
                return many;
            } else {
                firstGenerated = true;
                return once;
            }
        }
    }
};

and some small JSON encoding using it:

    result = "{ ";
    var comma = onceMany("", ", ");
    for (var key in object) {
        result += comma.next() + "'" + key.replace(/'/g, "\\'") + "' : " +  jsonStringify(object[key]);
    }
    result += "}";
 

Twitter

mhoye
mhoye It looks like C++ and Perl are in a bizarro-syntax wizard fight, and C++ is trying to consume the essence of Perl so it can become Perl 6.

2 weeks ago via Twitter for Android • 9 retweets

dchest
dchest Syntax highlighting pic.twitter.com/jqlpQCRpml

2 weeks ago via Twitter Web Client • 2283 retweets

bmst
bmst Here's one reason not to use #Lync. It doesn't work. #justwindowsthings

4 weeks ago via Twitter Web Client

Germanium

The one to rule them all. The browsers that is.

SharpKnight

SharpKnight is an Android chess game.

MagicGroup

MagicGroup is an eclipse plugin.

Go to top