Blocks In Java Discussion

Area to discuss or comment on the Wiki Article BlocksInJava -- RobertDiFalco


Discussion and Suggestions:

Very elegant! I implemented something similar (but simpler) for evolving programs with strongly typed sexual reproduction (aka crossover) in both Java and C++. However, my system was a much more basic use of the Interpreter pattern and didn't include curried functions.

One thing I included in my library was type safety. The Java version had reflective capabilities that could be used to ensure type safety when built in to the AST; each function or predicate had a method for querying the Class of the returned value and arguments. The C++ version used templates to ensure type safety at compile time. Have you considered type safety in your library?

Finally, are you planning to release this to the public? -- NatPryce

Nat, thanks. About type-safety, I've thought about it a bit. One part of me would like to add it explicitly while another part would like the ast package to be a foundation that one could construct a type-safety solution on top of (if needed for their solution domain). I do use some simple error checking in my implementation to ensure, for example, that the Object returned by a Function is a Boolean before retrieving its booleanValue in a Predicate. As you know, this sort of thing is much cleaner with C++ templates. I also started a GJ implementation and that was a joy. However, in actual use I was surprised at how sufficient a job the Java VM did of reporting type problems with un-checked exceptions. While that may be fine in some applications, it wont be in others.

I would like to release it publicly. In a way I have here. -- RobertDiFalco

As for releasing the package, how about setting up a SourceForge project? -- NatPryce

I finally got around to reading this page, and I am very impressed with the whole presentation. I've wanted something like this in the past - but I didn't have a clear idea as to what kind of infrastructure would work well, and at the time the desire didn't seem strong enough to warrant the work. Please do consider making the package itself available somewhere, and also register my interest in your abstract data types package. -- Brett Neumeier

Very Cool. The thought just occurred to me that I should atleast learn Smalltalk so I will know what is missing in Java. -- Venu Thachappilly

Wow. I am very impressed. This has given me a lot to think about. I get the gist from the text and code examples, however I've become stuck trying to actually code an InternalIterator of my own. I would be very grateful if you would publish the AST and ADT packages for others to use and learn from. -- EricHerman

A few of years later, I'm amazed that there was a time when the subject matter seemed at the edge of my understanding. I use blocks "all the time" now, and this page really changed the way I program in Java and thus gave me a window into understanding some of what is so nice about the way some other languages (Ruby, Smalltalk) handle blocks so nicely. This page will remain a wiki clasic for me. -- EricHerman

Robert, this is great stuff. Really elegant code. Writing interpreters for predicate trees in java is no fun at all, but this helps take the pain. I really miss prolog for this, but I may have learn some smalltalk now :-) Are you still thinking about making these packages (ast, adt) available? -- BillDehora

Robert, I am too lazy to assemble this document into Java source. You should put this on sourceforge soon. It would really be a significant contribution. -- ThomasEnebo

Using this document I've written my own version of these interfaces and classes in about three hours. I didn't go all the way with re-writing the Java collections; I'm using a static utility-type class to encapsulate the iterator mess but it works well and maybe sometime in the future I'll rework the collections for performance. Overall, this is a fantastic page and Robert did a great job summing up his work. Much appreciated, Robert. -- JeffPanici

Fantastic stuff. Unfortunately the ItemSequence interface flew completely over my head. How would one go about using that? I keep seeing Index as an STL iterator, which is probably not what it is at all. Could anyone who understands ItemSequence put up a code snippet that would show it's use, please? -- JonThoroddsen

I keep coming back to this, and I do like it; even though it illustrates the poverty of a language which cannot generate its own code and run it. I was wondering about whether it was worth adding parenthesis? I may be missing something in my partially grokked state, of course. -- RichardHenderson.

Binders are essentially parenthesis. -- RobertDiFalco

I have a project in SourceForge that is attempting to cover much the same ground. Look at http://jga.sf.net/ (JavaGenericAlgorithms)

There is also an apache project that seems to be working in the same conceptual area (I just found it today, myself). The apache project is http://jakarta.apache.org/commons/sandbox/functor/

-- DavidHall


For yet-another-set-of-functor-interfaces, these ones with java 1.5 generics and varargs, see http://www.dishevelled.org/functor -- MichaelHeuer


For those who would prefer true syntax and types for blocks and who can afford to use a Java extension instead of Java itself, you should look at the NiceLanguage. -- DanielBonniot


Building on RobertDiFalco's work, I have been using a couple of classes with some success. Admittedly, they do not achieve the performance gains of rewriting collections, but they work well and are conceptually simple. Both classes are wrappers for the existing java interfaces. -- AnonymousDonor


  public class InternalIterator
  {
    private Iterator at;

// constructor public InternalIterator( Iterator at ) { this.at = at; }

//* eval block for each public void enum( UnaryProcedure aBlock ) { while ( at.hasNext() ) aBlock.run( at.next() ); }

//* increment count for each true public int count( UnaryPredicate aBlock ) { int count = 0;

while ( at.hasNext() ) if (aBlock.is( at.next() )) count++;

return count; }

//* remove item for each block that answer true public void remove( UnaryPredicate aBlock ) { while ( at.hasNext() ) if ( aBlock.is( at.next() ) ) at.remove(); }

//* detect first for block answers true public Object detect( UnaryPredicate aBlock ) { while ( at.hasNext() ) { Object each = at.next(); if ( aBlock.is( each ) ) return each; }

return null; }

//* inject value into block with each item public Object inject( Object value, BinaryFunction aBlock ) { Object nextValue = value;

while ( at.hasNext() ) nextValue = aBlock.eval( nextValue, at.next() );

return nextValue; }

//* answer new collection for each true public Collection select( UnaryPredicate aBlock ) { Collection result = new ArrayList();

while ( at.hasNext() ) { Object each = at.next(); if (aBlock.is( each )) result.add( each ); }

return result; }

//* answer new collection for each false public Collection reject( UnaryPredicate aBlock ) { Collection result = new ArrayList();

while ( at.hasNext() ) { Object each = at.next(); if (!aBlock.is( each )) result.add( each ); }

return result; }

//* answer new collection of non-null results public Collection collect( UnaryFunction aBlock ) { Collection result = new ArrayList();

while ( at.hasNext() ) { Object each = aBlock.eval( at.next() ); if (each != null) result.add( each ); }

return result; } }

  public class AstCollection
    implements Collection
  {
    private Collection m_items;

//* constructor public AstCollection( Collection items ) { m_items = items; }

//* eval block for each public void enum( UnaryProcedure aBlock ) { getInternalIterator().enum( aBlock ); }

//* increment count for each true public int count( UnaryPredicate aBlock ) { return getInternalIterator().count( aBlock ); }

//* remove item for each block that answer true public void remove( UnaryPredicate aBlock ) { getInternalIterator().remove( aBlock ); }

//* detect first for block answers true public Object detect( UnaryPredicate aBlock ) { return getInternalIterator().detect( aBlock ); }

//* inject value into block with each item public Object inject( Object value, BinaryFunction aBlock ) { return getInternalIterator().inject( value, aBlock ); }

//* answer new collection for each true public Collection select( UnaryPredicate aBlock ) { return getInternalIterator().select( aBlock ); }

//* answer new collection for each false public Collection reject( UnaryPredicate aBlock ) { return getInternalIterator().reject( aBlock ); }

//* answer new collection of non-null results public Collection collect( UnaryFunction aBlock ) { return getInternalIterator().collect( aBlock ); }

//* wrap an Iterator with InternalIterator private InternalIterator getInternalIterator() { return new InternalIterator( iterator() ); }

/* (non-Javadoc) * @see java.util.Collection#add(java.lang.Object) */ public boolean add( Object o ) { return m_items.add( o ); }

/* (non-Javadoc) * @see java.util.Collection#addAll(java.util.Collection) */ public boolean addAll( Collection c ) { return m_items.addAll( c ); }

/* (non-Javadoc) * @see java.util.Collection#clear() */ public void clear() { m_items.clear(); }

/* (non-Javadoc) * @see java.util.Collection#contains(java.lang.Object) */ public boolean contains( Object o ) { return m_items.contains( o ); }

/* (non-Javadoc) * @see java.util.Collection#containsAll(java.util.Collection) */ public boolean containsAll( Collection c ) { return m_items.containsAll( c ); }

/* (non-Javadoc) * @see java.util.Collection#isEmpty() */ public boolean isEmpty() { return m_items.isEmpty(); }

/* (non-Javadoc) * @see java.util.Collection#iterator() */ public Iterator iterator() { return m_items.iterator(); }

/* (non-Javadoc) * @see java.util.Collection#remove(java.lang.Object) */ public boolean remove( Object o ) { return m_items.remove( o ); }

/* (non-Javadoc) * @see java.util.Collection#removeAll(java.util.Collection) */ public boolean removeAll( Collection c ) { return m_items.removeAll( c ); }

/* (non-Javadoc) * @see java.util.Collection#retainAll(java.util.Collection) */ public boolean retainAll( Collection c ) { return m_items.retainAll( c ); }

/* (non-Javadoc) * @see java.util.Collection#toArray() */ public Object[] toArray() { return m_items.toArray(); }

/* (non-Javadoc) * @see java.util.Collection#toArray(java.lang.Object[]) */ public Object[] toArray( Object[] a ) { return m_items.toArray( a ); }

/* (non-Javadoc) * @see java.util.Collection#size() */ public int size() { return m_items.size(); } }
From the above code... me thinks someone's been looking at SmallTalk's collection hierarchy, I say that because I HaveThisPattern, and wrote something similar for my own collections.
See BlocksInManyLanguages, BlocksInCsharp
CategoryObjectFunctionalPatterns | CategoryClosure | CategoryJava

EditText of this page (last edited December 17, 2006) or FindPage with title or text search