oi

Oi: checked IO a stream can carry, failed unchecked

IoFunction and IoConsumer let a stream map through and end in IO: each is a Function or Consumer whose work throws IOException, rethrown as UncheckedIOException.

Rationale

Why. A stream's Function and Consumer cannot throw IOException, yet reading or writing a file is often the step a stream needs.

Key Concepts

Checked IO in a chain

Role. A lambda cast to IoFunction<T, R> or IoConsumer<T> implements io, which may throw IOException, and is the Function or Consumer a stream's map or forEach takes.

Pattern. Template Method

How It Works

Guarantees. An IOException thrown by io leaves apply or accept as an UncheckedIOException whose cause is that IOException. No method takes null and IoFunction never returns it, declared with contrax's @PreCondition(IsNotNull.class) and @PostCondition(IsNotNull.class).

Lane

Purpose. Mapping through and ending a stream in IO, where any IO failure stops the stream.

Alternative. A loop with its own try/catch, when one element's IO failure is recovered from and the rest go on.

Usage

Without oi: a try/catch in every lambda

places.stream()
        .map(place -> {
            try {
                return place.toRealPath();
            } catch (final IOException failed) {
                throw new UncheckedIOException(failed);
            }
        })
        .forEach(place -> {
            try {
                Files.delete(place);
            } catch (final IOException failed) {
                throw new UncheckedIOException(failed);
            }
        });

With oi: the lambda is cast, and throws

places.stream()
        .map((IoFunction<Path, Path>) Path::toRealPath)
        .forEach((IoConsumer<Path>) Files::delete);

Dependencies

  • software.visionary:junit-closure:2026.09.17 at Testing

Views

Drawn from the release. A link in a view opens its source at the release tag.

architecture.svg
architecture.svg
classes.software.visionary.oi.svg
classes.software.visionary.oi.svg
packages.svg
packages.svg