Below you will find pages that utilize the taxonomy term “Chop”
chop: When Every Command Returns the Same Kind of Thing
July 15, 2025
Section 2.2 of Structure and Interpretation of Computer Programs introduces the closure property: the result of combining things should be the same kind of thing you started with. cons two values and you get a pair, which you can cons again. This is what makes recursive data structures possible. Without it, you get flat records. With it, you get trees, lists, nested structure of arbitrary depth.
Abelson and Sussman are careful to distinguish this from lexical closures (functions that capture their environment). Algebraic closure is about the type signature of combination: if the output type matches the input type, composition is unlimited.
Most discussions of closure treat it as a property to verify. You check whether your algebra is closed and move on. But closure is more powerful than that. It’s a design method: choose a type, force every operation to consume and produce that type, and see what emerges. The constraint does the creative work.
chop is an image-manipulation CLI built on exactly this principle. 27 commands. One rule: read JSON from stdin, write JSON to stdout.
The Problem with Image Pipelines
Traditional image CLIs violate closure. ImageMagick consumes a file and produces a file. Each invocation is terminal. The output is pixels, not something you can pipe into further processing without going back to disk. Composition happens through flag accumulation inside a single command, not through the shell’s native composition mechanism.
You can’t tee a midpoint. You can’t save a half-finished pipeline as a recipe and apply it later. You can’t branch.
The SICP parallel is direct: if cons produced an atom instead of a pair, you could build flat structures but not recursive ones. If an image command produces pixels instead of a composable description, you can build single transformations but not pipelines.
One Constraint: JSON In, JSON Out
Every chop command reads a PipelineState JSON object from stdin, appends one operation, and writes the updated JSON to stdout. The wire format carries no image data, only a recipe:
{
"version": 3,
"ops": [
["load", ["photo.jpg"], {}],
["resize", ["50%"], {}],
["pad", [10], {"color": "white"}]
],
"metadata": {}
}
Each operation is a [name, args, kwargs] triple. The pipeline accumulates operations as data. Here’s what this looks like in practice: