JTamaro is a Java educational library designed for teaching problem decomposition using graphics.
JTamaro is a close cousin to the
PyTamaro compositional graphics
library for Python.
Unlike PyTamaro, JTamaro also includes simple purely functional data
structures (with types like Sequence, Option, and Pair), and functionality
for developing purely-functional interactive applications (with a fluent API to
configure and run an Interaction).
JTamaro provides a minimal API, much smaller than the Java API surface covered
in standard Java programming courses.
The library promotes purity, immutability, parametric polymorphism, subtyping polymorphism, and higher-order functions. It does this by focusing on interfaces, generics and modern features of the Java programming languages such as records, and by a design that encourages immutability and the composition of independent components.
It is featured in our textbook, Composition in Java.
Provides implementation for the following types:
Either: values with two possibilitiesFunction{0-4}: interfaces for function objects with up to 4 argumentsOption: the Maybe monad. Used to handle errors or exceptional casesPair: tuple of two elementsSequence: ordered list of elements of a given type
import jtamaro.graphic.Colors;
import jtamaro.graphic.Graphic;
import jtamaro.graphic.Graphics;
import jtamaro.io.GraphicIO;
void main() {
final Graphic floor = Graphics.rectangle(100, 100, Colors.YELLOW);
final Graphic roof = Graphics.rectangle(100, 100, 60, Colors.RED);
final Graphic house = Graphics.above(roof, floor);
GraphicIO.show(house);
}Interaction allows to develop an interactive application:
import static jtamaro.graphic.Colors.*;
import static jtamaro.graphic.Fonts.*;
import static jtamaro.graphic.Graphics.*;
import static jtamaro.interaction.KeyboardKey.*;
import static jtamaro.io.GraphicIO.*;
void main() {
interact(0)
.withKeyReleaseHandler((model, key) -> model + switch (key.keyCode()) {
case UP -> 1;
case DOWN -> -1;
default -> 0;
})
.withRenderer(model ->
text(String.valueOf(model), MONOSPACED, 100, BLACK))
.run();
}The colors and graphics are pure.
Code that performs side effects (e.g., showing a graphic on the screen) is
accessible through methods of classes in the jtamaro.io package.
Optics are a composable notion of substructure. They can be used to easily traverse and modify arbitrarily complex data structures.
An annotation processor (:processor) is provided to automatically generate
Lenses for components of record classes annotated with @Glasses.
Additional Traversals and Lenses are also generated for those components of
type Sequence.
This project uses Gradle. It contains multiple subprojects:
example- An application that shows how to use the features of the library.lib- Main jTamaro module. It includes the data structures, graphics, interaction and I/O.music- A midi-based music library that allows to play notes and chords.processor- An annotation processor for the automatic generation of optics for record classes.
To just the build library's jar file for usage in other projects:
./gradlew :lib:jarThe output will be in lib/build/libs/lib-*.jar
To build everything and run the example app:
./gradlew :example:runTo run individual demos in the example app, run the corresponding classes
with main methods in the example directory from within an IDE that
understands Gradle (e.g., VS Code) and thus will find (and if needed build) the
library.
Note: The library is targeting Java 25, and it makes extensive use of the latest additions to the language (records, sealed classes, pattern matching...). Older Java versions are not supported.
The documentation is published at
this link, or it can be
generated by running the following command (output at lib/build/docs/javadoc):
./gradlew :lib:javadoc