liveBook · Manning

Fits

As explained in Fabulous Adventures in Data Structures and Algorithms

Fits is the book-specific method that determines whether a Doc can be rendered within a remaining line width without turning descendant optional breaks into line breaks.

Fits answers whether a Doc can occupy the remaining line width while treating every descendant optional break as inline text. A successful check means Pretty can avoid inserting line breaks; failure permits the formatter to break instead. section 9.3.3

Rather than recurse through a potentially deep document graph, Fits stores pending work in a growable Stack<Doc>. It tracks characters used, stops immediately when the width is exceeded, and succeeds when no documents remain. section 9.3.3 section 9.3.2

The traversal applies a small rule to each Doc variant:

  • TextDoc consumes its text length and fits only while the accumulated width remains acceptable. section 9.3.3
  • GroupDoc and IndentDoc push their child for inspection; indentation affects later rendering rather than Fits’ character count. section 9.3.3
  • OptBreakDoc counts its inline text, so a zero-width break always fits but a space can exceed the remaining width. section 9.3.3
  • ConcatDoc processes its left child before its right child, allowing the remaining width to flow across the concatenation. section 9.3.3
Listing 9.3 A nonrecursive Fits method
abstract record class Doc
{
    // […]
    private bool Fits(int width)
    {
        var docs = new Stack<Doc>(); #1
        docs.Push(this); #2
        int used = 0; #3
        while (true) 
        {
            if (used > width) #4
                return false;
            if (docs.Count == 0) #5
                return true;
            Doc doc = docs.Pop();
            switch (doc)
            {
                case TextDoc td:
                    used += td.text.Length;
                    break;
                case GroupDoc gd:
                    docs.Push(gd.doc);
                    break;
                case IndentDoc id:
                    docs.Push(id.doc); #6
                    break;
                case OptBreakDoc bd:
                    used += bd.text.Length; #7
                    break;
                case ConcatDoc cd:
                    docs.Push(cd.right); #8
                    docs.Push(cd.left);
                    break;
            }
        }
    }
    // […]

The listing shows the explicit work stack, width counter, termination checks, and type-based traversal used by the nonrecursive implementation. section 9.3.3

Formatting Foo.Bar(xx + yy * zz)

A document assembled from groups, indentation, concatenation, and optional breaks is rendered at width 20 as: Foo.Bar( xx + yy * zz) Fits tests whether the whole grouped layout can remain on one line before Pretty chooses this multiline result. section 9.3.1

How Fabulous Adventures in Data Structures and Algorithms covers it

How deep it goes
Implements a nonrecursive stack traversal with per-Doc rules, stopping short of choosing the final line-break layout.
Examples
Uses Foo.Bar(xx + yy * zz), a width of 20, and the resulting indented multiline output.
What it assumes
Assumes Doc variants and optional-break semantics while defining their Fits behavior through concrete traversal rules.
What you can do after
Build it from scratch as a stack-based width test over a hierarchy of Doc variants.
How it connects
Connects Doc, Pretty, optional breaks, groups, indentation, concatenation, and greedy pretty printing.

This explainer was generated by Manning's knowledge graph from the text of Fabulous Adventures in Data Structures and Algorithms. The section links point to the parts of the book it draws on.