The Artima Developer Community
Sponsored Link

Scala Buzz
Java 7 Example - Writing Your Own Foreach

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Ricky Clarkson

Posts: 63
Nickname: rclarkson
Registered: Jul, 2006

Ricky Clarkson is a salsa-dancing, DJing programmer in Manchester, England.
Java 7 Example - Writing Your Own Foreach Posted: Jan 24, 2008 1:21 PM
Reply to this message Reply

This post originated from an RSS feed registered with Scala Buzz by Ricky Clarkson.
Original Post: Java 7 Example - Writing Your Own Foreach
Feed Title: Ricky's technical blog
Feed URL: http://rickyclarkson.blogspot.com/feeds/posts/default
Feed Description: A blog about programming languages, and Java.
Latest Scala Buzz Posts
Latest Scala Buzz Posts by Ricky Clarkson
Latest Posts From Ricky's technical blog

Advertisement
One of the promises of closures was that if Java 5 had closures instead of foreach, you could have implemented foreach as a method. Let's put that to the test with the Java 7 prototype.

Firstly, the 'control invocation syntax', which is a little subjective, hasn't been implemented in the prototype, so anything I show here is certainly less than foreach could be with closures.

Here's a simple attempt:

public static <T> void foreach(T[] ts,{T=>void} block)
{
    for (int a=0;a<ts.length;a++)
        block.invoke(ts[a]);
}
I can call this like so:

foreach(new String[]{"hello","world"},{String s=>System.out.println(s);});

I found that I kept repeating one error in testing out this prototype, namely forgetting the ; for a statement in a {something=>void} closure.

Anyway, the above doesn't work with continue, break or return. Those are not bound yet by the closures prototype. No matter, let's roll our own (ignoring return; I don't know of a way to apply the following technique to return).

Not only can we pass a closure to a method, but the method can pass a closure to our closure! No, I've not yet gone mad:

public static <T> void foreach(T[] ts,{T,{=>void},{=>void}=>void} block)

Perhaps the T,{=>void},{=>void} is better abstracted into a ForeachControl class or something. Imagining that it was, the T field would be called 't', the first {=>void} would be called 'brake' (as in break, but avoiding collisions with the keyword), and the second {=>void} would be called 'cont' (as in continue).

For now, I'm quite happy to use the above. I'll just reiterate it:

{T,{=>void},{=>void}=>void} is a function type that takes a T, and two {=>void}s and has no return value. A {=>void} is a function type that takes nothing and returns nothing, analogous to Runnable. Here's some example usage:


String[] input={"fish","print","fingers","don't print"};

foreach(input,{String s,{=>void} cont,{=>void} brake=>
        if (s.startsWith("fish"))
                cont.invoke();

        System.out.println(s);

        if (s.startsWith("fingers"))
                brake.invoke();
});
Ok, that kind of looks like a foreach statement now, plus some baggage for loop control. Actually that's as far as I can go in the current prototype. Let's implement foreach then.

cont and brake both need to 'send a message' to the foreach method, without allowing the closure to finish. Without convoluting the usage code above, I can do that by making cont and brake throw exceptions, which is very similar to how continue and break are planned to be supported in closures, except I'm doing it in-language.

public static <T> void foreach(T[] ts,{T,{=>void},{=>void}=>void} block)
{
    class Continue extends RuntimeException { }
    class Break extends RuntimeException { }

    for (int a=0;a<ts.length;a++)
    {
        try
        {
            block.invoke(ts[a],{=>throw new Continue();},{=>throw new Break();});
        }
        catch (Continue c)
        {
            continue;
        }
        catch (Break b)
        {
            break;
        }
    }
}
Look at the block.invoke line. I'm passing two closures to block.invoke - one that throws a Continue and one that throws a Break. Other than that, this method is pretty simple.

As I've said elsewhere, even when/if the control invocation syntax appears, you won't be able to implement foreach exactly as in Java 5, because int cannot be a type parameter, and the closures spec doesn't specify any boxing between int and Integer for type parameters.

Even if you never use this code (I won't!), you can see at a small scale the power of thinking in closures, especially for implementing language features. This is one of the reasons why Smalltalk was such a small language - you could implement much of what Java programmers think of as language as library methods. Lisp and FORTH are small languages (at least conceptually - ignore Common Lisp!) for similar reasons. Java 7 is aiming in the same direction.

Read: Java 7 Example - Writing Your Own Foreach

Topic: Java 7 Example - Writing Your Own Foreach Previous Topic   Next Topic Topic: Programming Language Continuum

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use