liveBook · Manning

Finalizer

As explained in Functional Programming in Scala, Second Edition

A finalizer is a cleanup action associated with an acquired resource and run when its scope is closed.

A finalizer is an effectful cleanup action associated with an acquired resource. Resource management registers the action with an open scope, then runs it when that scope closes. This makes cleanup part of the streaming computation rather than an afterthought. section 15.3.3

Scopes form a tree. Closing a scope first closes its subscopes and then evaluates its own finalizer. A finalizer is represented as F[Unit], so cleanup remains explicit, effectful, and composable. section 15.3.3

Resource-safe streaming must finalize resources when:

Nested scopes preserve cleanup structure. Subscope finalizers run in reverse registration order, followed by the enclosing finalizer. Cleanup continues after an individual failure, while the first observed error is retained and reported after the remaining finalizers have run. section 15.3.3

Closing a file

Stream.resource(Task(Source.fromFile(path)))(s => Task(s.close())) acquires a Source and registers s.close() as its finalizer. A file-writing stream uses the same pattern for BufferedWriter, ensuring that the writer is closed when processing finishes, stops early, or fails. section 15.3.3 section 15.6

The public resource pattern matters more than its implementation: acquire a value, expose it as a stream, and pair it with release logic that receives the acquired value. The scope machinery supplies the operational guarantee. section 15.3.3

def resource[F[_], R](acquire: F[R])(release: R => F[Unit]): Stream[F, R]

Use the resource constructor to connect an acquisition effect with a value-dependent finalizer. section 15.3.3

How Functional Programming in Scala, Second Edition covers it

How deep it goes
Explains scope trees, reverse-order closure, effectful state, and error retention, while treating implementation details as secondary.
Examples
Demonstrates file readers and buffered writers whose close actions serve as resource-dependent finalizers.
What it assumes
Assumes familiarity with effect types and streams while introducing scopes and Ref as implementation mechanisms.
What you can do after
Apply it via Stream.resource to pair effectful acquisition with value-dependent cleanup.
How it connects
Connects finalizers to resource safety, scopes, effect types, Ref, and stream processing.

This explainer was generated by Manning's knowledge graph from the text of Functional Programming in Scala, Second Edition. The section links point to the parts of the book it draws on.