jga is a functors library: the intent is to explore and exploit
functors as a design and implementation tool to reduce boilerplate
coding. A functor is an object that encapsulates a function or
expression: it can take arguments and produce results, as can any
method, expression, or function (in other languages that support
functions). Unlike an expression, as an object it can be passed as an
argument without being executed; it can be persisted to a database or
file; it can be serialized and passed from client to server (and
back); and it can be instantiated at runtime based on information
unavailable at compile-time.
How many times have you...
- ...found a method that does almost exactly what you want, except for
one or two lines?
- ...created a new class in order to override one simple method, because
it is almost what you need?
- ... written a boilerplate implementation of an interface that knows
about your specific business objects or your specific application?
- ... copied an entire class to change the one line or method rather
than refactoring it?
Functors provide a mechanism that can reduce all of the design
problems: they allow you to (in effect) pass a line of code as an
argument to a constructor or method, giving you a way to parameterize
objects on simple behavour.
jga borrows the functors from C++ STL library, and extends them with
functors that are natural for java programmers. jga also borrows the
notion that basic functors implementing common operations can be
profitably combined into compound structures to implement more useful
logic.
Compound functors of the type that jga promotes fall naturally into a
tree structure. Taking advantage of this yields a use of functors
that may be relatively new to many: as a form of executable metadata
that can be interpreted for the information embodied in the structure.
To facilitate this, all jga functors provide support for a Visitor
implementation.
The most natural application of a functor library is in the
implementation of common algorithms, such as those defined in STL.
jga provides a set of such algorithms that have been adapted to java
conventions and idioms, as opposed to being a direct port of STL.
An area that is rife with one line interfaces is event driven programming
of the sort that is typified by Swing. jga includes the beginnings of a
set of tools for use in GUI coding that addresses the common problems
described above: the continual reinvention of the same set of small
wheels in the set of listeners, editors, renderers, and models that
accompany a typical Swing program.
jga 0.8.1 now available
Sep. 15, 2009
jga: Generic Algorithms for Java, release 0.8.1 is now available
The hilights of this release are;
-
More support for variable length Functors in the API and in JFXG. Functors now
support compound forms, allowing arguments to be bound, generated, or computed by
nested functors.
-
New Algorithms: Flatten (return the contents of two dimensional data structures in
a single iterator), Compare (compares the contents of two data sources), and
Summarize.lookup (returns the first value in a data source that meets some
arbitrary criteria).
-
JFXG is now a JSR-223 compliant scripting langauge, with additional support for
functors that take an arbitrary number of arguments, local variables, and assignment
forms.
This release is compatable with Java 1.5 or later.
jga 0.8 now available
Dec 19, 2006
jga: Generic Algorithms for Java, release 0.8 is now available
The hilights of this release are;
-
Dual license structure: JGA can now be distributed via either the LGPL or the CDDL.
-
util reorginization: the util package is being reorganized to make it easier to
find and use the algorithms in the library
-
more concise functor creation: at the suggestion of users, the vast majority of
the functors in the library may now be built via static methods.
This release is compatable with either Java 1.4 or Java 1.5.
jga 0.7 now available
Apr 5, 2005
jga: Generic Algorithms for Java, release 0.7 is now available
The hilights of this release are;
- Support for the Java 1.5.0_02
-
The new FunctorParser (and it's typesafe extension GenericParser)
allow functors to be described using java-like syntax: the parser
creates the functor that implements the logic described in the
expression.
-
Hacker's Worksheet is the next phase in the evolution of the
Spreadsheet engine included in the prior release. This application
uses the FunctorParser to implement a spreadsheet whose expression
langauge looks like java in most respects.
This release is compatable with either Java 1.4 or Java 1.5.
A Java Hacker's Worksheet (preview)
Dec 13, 2004
The Spreadsheet widget in the net.sf.jga.swing package grew out of a couple
of design goals behind the jga library. The first was that a spreadsheet
could be thought of as a sparse matrix of function objects. The second was
that to really use a spreadsheet would require some language that the user
could enter into the cells. A 'scripting' capability that would allow
a much easier method for creating compound functors has always been on the
list of goals for this project.
The parser and spreadsheet have both advanced in development now to the
point where it's time to get some feedback. Neither is in its final state,
yet, but both are somewhat usable. To that end, I've published an applet
version of the Java Hacker's
Worksheet. I'm very interested in getting some feedback on this,
particularly in cases where it doesn't work in some unexpected way.
There's a javadoc extract for the
expression language and the
parser in their current form.
You can use the parser programatically. There's an example of building a
reasonably compound formula in the
jga & the java 1.5 forloop
where the goal is to generate random coin flip. To build the functor
programatically, you would use the following declaration.
Generator<Boolean> coinflip =
new LessEqual<Double>().bind2nd(0.5d).generate(new Random());
Using the FunctorParser (or in this case, the generified derivitive
GenericParser), you would use the following declaration:
GenericParser parser = GenericParser.getInstance();
...
Generator<Boolean> coinflip =
parser.parseGenerator("Math.random() <= 0.5d", Boolean.class);
There are three main methods in the FunctorParser: one that returns a Generator, one
that returns a UnaryFunctor, and one that returns a BinaryFunctor. The GenericParser
contains similar methods, but each takes an extra class reference in order to check
the return type of the resulting functor.
/**
* Parses the string to create a Generator.
*/
public Generator parseGenerator(String str) throws ParseException;
/**
* Parses the string to create a UnaryFunctor that takes an argument of the
* given type.
*/
public UnaryFunctor parseUnary(String str, Class argType)
throws ParseException;
/**
* Parses the string to create a BinaryFunctor that takes arguments of the
* given types.
*/
public BinaryFunctor parseBinary(String str, Class arg1Type, Class arg2Type)
throws ParseException;
jga Project Blog at JRoller
Dec 5, 2004
I've started a blog entitled
"Scraps from a Messy Desk" on
JRoller.com that I intend to use (at least
in part) as a resource for generating documentation for jga. I've already
put in a couple of entries about the project's history and motivation, and
I also expect to use it as a sounding board for trying out new content that
will eventually be used to improve this site.
There's a link to the blog in the header. Additionally, I'll probably be
permalinking to specific entries from the documentation page when it makes
sense.
Java 1.4 Compatability
Feb 17, 2004
Sun recently released the first beta version of the 1.5 JDK. I've
converted this project to use the new beta: everything works as
expected although the new compiler generates many more warnings than
the old compiler did. However, classes compiled with 1.5 syntax may
not be used with previous versions of the JDK or JRE. For a little
more information, see this
thread
on Sun's Java forums. There was a far lengthier thread that
contained more information about Sun's decision, but unfortunately,
the controversy caused a few posters to generate too many flames
toward Sun's developers, and the thread has been deleted.
I've decided for my own project that abandoning the 1.4 jdk is not an
option, at least for now. From this point, and for as long as I can
reasonably do so, I will maintain two versions of jga. From this
release forward, I'll designate the version for use with the 1.4 jdk
with an 'a' suffix to the version number, and the version for use
with the 1.5 beta jdk with a 'b' suffix. As long as I can keep the
codebase the same and simply use different build mechanisms to
produce the two versions, I'll do so. If Sun introduces some new
incompatable syntax during the beta period or if the effort to keep
the two versions in sync becomes too great (neither of which I
consider likely), then I'll have to reconsider.
With the release of the 1.5 beta compiler, I've decided to elevate
the status in the SourceForge trove to 'beta'. I have considered
breaking the swing package out into a separate delivery, as the
'core' part of the library (ie, the fn and util packages) is largely
complete and the swing package will likely continue to grow. The
justification for breaking out the swing package is that, IMO, the
'beta' level is more appropriate when the scope of the package is
complete and the remaining work is bug fixes. On the other hand,
with the necessity of creating a second set of deliverables to
support the new 1.5 beta JDK, I didn't want the number of
different jar files being downloaded to explode. For now, the swing
package is still expected to grow in functionality even though the
overall project is in a 'beta' phase. As before, I expect that all
code in the library is stable (the earlier 'alpha' status was a
reflection of expected growth everywhere in the library).
jga & the Java 1.5 forloop
May 15, 2004
One of the new features in Java 1.5 is the new forloop syntax. The new
forloop is analagous to a foreach construct that is common in other
languages. The syntax hides the existance of an iterator, and is even
extended to cases that didn't have an iterator before (arrays). It
also extends to enumerated types.
So, if hiding the iterator is a step forward, can we take things
another step and capture more of the common patterns as part of the
loop mechanism? The answer is 'sort of'. We can't completely hide
the fact that decisions are being made, and that some elements are
being processed. What we can do is hide a lot of the mechanics of
the process.
System Requirements & Installation
May 10, 2004 (updated Sept 10, 2009)
jga may be used with Java 1.5 or later. The JFXG scripting langauge
is usable with Java 1.6 or later, or with Java 1.5 and the separately
packaged scripting API's.
If you want to use the included test framework, you'll need
jUnit 3.8.1 or later, and
jfcUnit 1.0.3.
To build jga from source will
require ant 1.6.2 and
javacc 3.2.
Installation
Installation is pretty trivial -- unpack the distribution and put
either jga-0.6.jar or jga-0.6-retro.jar on your CLASSPATH.