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 Item''''''Sequence 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 Item''''''Sequence 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 '''I''''''nternalIterator''' { private Iterator at; // constructor public I''''''nternalIterator( Iterator at ) { this.at = at; } //* eval block for each public void '''enum'''( U''''''naryProcedure aBlock ) { while ( at.hasNext() ) aBlock.run( at.next() ); } //* increment count for each true public int '''count'''( U''''''naryPredicate 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'''( U''''''naryPredicate aBlock ) { while ( at.hasNext() ) if ( aBlock.is( at.next() ) ) at.remove(); } //* detect first for block answers true public Object '''detect'''( U''''''naryPredicate 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, B''''''inaryFunction aBlock ) { Object nextValue = value; while ( at.hasNext() ) nextValue = aBlock.eval( nextValue, at.next() ); return nextValue; } //* answer new collection for each true public Collection '''select'''( U''''''naryPredicate aBlock ) { Collection result = new A''''''rrayList(); 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'''( U''''''naryPredicate aBlock ) { Collection result = new A''''''rrayList(); 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'''( U''''''naryFunction aBlock ) { Collection result = new A''''''rrayList(); while ( at.hasNext() ) { Object each = aBlock.eval( at.next() ); if (each != null) result.add( each ); } return result; } } ---- public class '''A''''''stCollection''' implements Collection { private Collection m_items; //* constructor public A''''''stCollection( Collection items ) { m_items = items; } //* eval block for each public void '''enum'''( U''''''naryProcedure aBlock ) { getInternalIterator().enum( aBlock ); } //* increment count for each true public int '''count'''( U''''''naryPredicate aBlock ) { return getInternalIterator().count( aBlock ); } //* remove item for each block that answer true public void '''remove'''( U''''''naryPredicate aBlock ) { getInternalIterator().remove( aBlock ); } //* detect first for block answers true public Object '''detect'''( U''''''naryPredicate aBlock ) { return getInternalIterator().detect( aBlock ); } //* inject value into block with each item public Object '''inject'''( Object value, B''''''inaryFunction aBlock ) { return getInternalIterator().inject( value, aBlock ); } //* answer new collection for each true public Collection '''select'''( U''''''naryPredicate aBlock ) { return getInternalIterator().select( aBlock ); } //* answer new collection for each false public Collection '''reject'''( U''''''naryPredicate aBlock ) { return getInternalIterator().reject( aBlock ); } //* answer new collection of non-null results public Collection '''collect'''( U''''''naryFunction aBlock ) { return getInternalIterator().collect( aBlock ); } //* wrap an Iterator with I''''''nternalIterator private I''''''nternalIterator '''getInternalIterator'''() { return new I''''''nternalIterator( 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