Proposal: Block Expressions for Java

Tim Peierls tim at peierls.net
Fri Mar 6 12:50:23 PST 2009


I kind of like Neal's block expression proposal, but I am struggling to find
more compelling examples for it. Instead of

*super((double pi = Math.PI ; pi*pi)**);*

it would be clearer to write

*super(Math.PI * Math.PI**);*

Instead of

public static final Map<Integer,Integer> primes = (
    Map<Integer,Integer> t = new HashMap<Integer,Integer>();
    t.put(1, 2); t.put(2, 3); t.put(3, 5); t.put(4, 7);
    Collections.unmodifiableMap(t));

it would be better to use a Builder like the one in Google Collections'
ImmutableMap:

public static final ImmutableMap<Integer, Integer> PRIMES =     new
ImmutableMap.Builder<Integer, Integer>()
        .put(1, 2).put(2, 3).put(3, 5).put(4, 7)
        .build();

That particular example could in turn be rewritten more simply as

public static final ImmutableMap<Integer, Integer> PRIMES =
    ImmutableMap.of(1, 2, 2, 3, 3, 5, 4, 7);

So while I understand the intention behind these examples, I think they
could be improved.  Any ideas?

What I like about the proposal is the ability to add side-effects in places
I currently can't without distorting the existing logic. For example, let's
say I want to add logging of the value computed in the while-loop test
of this fragment:

while (jobsRemaining() > 0) {
    processSomeJobs();
}

I could write:

int j = jobsRemaining();
log.info("jobs remaining = %d", j);
while (j > 0) {
    processSomeJobs();
    j = jobsRemaining();
    log.info("jobs remaining = %d", j);
}

but that means repeating the logging statement and introducing a variable j
with scope greater than the while loop. If I don't introduce a variable I
have to repeat the call to jobsRemaining(), which might not be appropriate
if it's an expensive call (and I'd still have to repeat the logging call).

I could write a helper method instead:

int computeAndLogJobsRemaining() {
    int j = jobsRemaining();
    log.info("jobs remaining = %d", j);
    return j;
}
...
while (computeAndLogJobsRemaining() > 0) {
    processSomeJobs();
}

but that's adding a lot of machinery for something as conceptually simple as
this. Similarly for solutions involving method interception.

The proposed enhancement would (I think) let me write something like this:

while ((
    int j = jobsRemaining();
    log.info("jobs remaining = %d", j);
    j > 0
)) {                    // are two levels of parens necessary?
    processSomeJobs();
}

which is exactly what I wanted to say, without having to change the
structure of the original code.

Could I get along without this? Absolutely.  Would I find it useful?  Yes,
occasionally it would be quite handy.

--tim



More information about the coin-dev mailing list