In Ruby, when does pp print differently from p, and how can a class customise its pp output with pretty_print?
answer
- same return value as p
- wraps at width minus one
- custom inspect is used verbatim
- pretty_print(q) with group and breakable
- pretty_inspect returns the string
basics
~20 spp prints the same inspect-style text as p but breaks values wider than the output width over indented lines; a class customises it by defining pretty_print(q) with the PP builder's group, text, breakable and pp calls.
solid answer
~40 sFor short values `pp` and `p` print the same line and both return their argument. When the text would exceed the width - the terminal width, else `COLUMNS`, else 80, minus one - `pp` breaks arrays, hashes and objects over indented lines. For an object that keeps `Kernel#inspect`, `pp` lists its instance variables sorted by name, each pretty-printed; if the class overrides `inspect`, `pp` uses that string as it is, without line breaks. To control the layout, define `pretty_print(q)` and describe the structure with the builder: `q.object_group(self)` or `q.group` for brackets, `q.text` for literal text, `q.breakable` for a space that may become a newline, `q.pp` for nested values and `q.seplist` for comma-separated lists. `pretty_inspect` returns the same text as a String.
code
ruby · 19 linesclass Timetable
def initialize(station, departures)
@station = station
@departures = departures
end
def pretty_print(q)
q.object_group(self) do
q.breakable
q.text @station
q.breakable
q.seplist(@departures) { |d| q.pp d }
end
end
end
t = Timetable.new("Leeds", ["08:15", "09:40"])
pp t # #<Timetable Leeds "08:15", "09:40">
s = t.pretty_inspect # same text as a String, with a trailing newlinego deeper
Recall that pp is p for big structures: same inspect-style text and return value, but spread over lines when it is too wide.
Explain the width rule and the builder: groups break as a unit, breakables turn into newlines, and a custom inspect is printed as one unbreakable piece.
Add pretty_print only to objects you dump often, such as parse trees or configuration graphs, and check it agrees with any inspect filtering of secrets.
Weigh a shared pretty_print convention against simple inspect overrides for a codebase's debugging ergonomics; it is a small, optional investment.
`Kernel#pp` is the pretty-printing sibling of `Kernel#p`. Both write a developer-facing representation followed by a newline and both return their argument, but `pp` is built on the **pp** and **prettyprint** libraries, which lay text out to fit a width. Interviewers ask about it to see whether you know when the output differs and how the hook works. ## When pp and p differ For a value whose single-line form fits, `pp` and `p` print the same thing. The differences: - **Line breaking.** When the output would exceed the width, `pp` breaks nested arrays, hashes and objects across lines with indentation. `p` always writes one line. - **Width.** `PP.width_for` uses the terminal's width minus one when writing to a terminal, otherwise the `COLUMNS` environment variable, otherwise 80, minus one. - **Plain objects.** For an object that keeps `Kernel#inspect`, `pp` does not call `inspect`; it renders `#<Klass:0x...` and then each instance variable, **sorted by name**, pretty-printing every value. `p` shows them in definition order on one line. - **Custom inspect.** If the class overrides `inspect`, `pp` uses that string verbatim - it has no break points, so it never wraps. Since Ruby 2.5, `pp` needs no `require`; the first call loads the library. ## The pretty_print hook To make a class pretty-print well, define `pretty_print(q)`. The argument is a layout builder; you describe structure and it decides where lines break. | Builder call | Purpose | |---|---| | `q.text(str)` | literal text that is never split | | `q.breakable` | a space that becomes a newline plus indentation if the group does not fit | | `q.group(indent, open, close) { ... }` | a unit that is broken as a whole, with optional brackets | | `q.object_group(obj) { ... }` | a group opened with `#<ClassName` and closed with `>` | | `q.nest(indent) { ... }` | extra indentation for lines broken inside the block | | `q.pp(value)` | pretty-print a nested value with its own `pretty_print` | | `q.seplist(list) { ... }` | yield each element with `q.comma_breakable` between them | | `q.comma_breakable` | a comma followed by a breakable space | The layout algorithm tries to fit each group on the current line; only when it does not fit does it turn that group's breakables into newlines. Inner groups that still fit stay on one line. ## A worked example A timetable object holding a station name and a list of departures: ```ruby class Timetable def initialize(station, departures) @station = station @departures = departures end def pretty_print(q) q.object_group(self) do q.breakable q.text @station q.breakable q.seplist(@departures) { |d| q.pp d } end end end ``` With a short list, `pp timetable` prints `#<Timetable Leeds "08:15", "09:40">` on one line. With forty departures, the group no longer fits, so each breakable becomes a newline and the departures run down the screen, indented by one column. ## Related methods 1. **`pretty_inspect`** returns the pretty-printed text as a String instead of writing it, handy for a log message. 2. **`PP.pp(obj, out, width)`** writes to any object that accepts `<<`, such as a String or an IO, with an explicit width. 3. **`PP.singleline_pp(obj, out)`** runs the same `pretty_print` logic without line breaks. 4. **`pretty_print_inspect`** can be aliased as `inspect` so `p` reuses the `pretty_print` layout on one line; it raises if the class did not override `pretty_print`. ## When to bother ## Cycles and shared objects The pp library also guards against infinite recursion. If an object is reached again while it is still being printed - a parent node pointing back at its child's parent, say - pp calls `pretty_print_cycle` instead, which by default prints `#<Klass:0x... ...>` with an ellipsis. Arrays and hashes print `[...]` and `{...}` in the same situation. A custom `pretty_print` that uses `q.pp` for nested values inherits this protection automatically, whereas code that concatenates `inspect` strings by hand can recurse until the stack overflows. ## When to bother Most classes never need `pretty_print`: `Struct`, `Data`, arrays and hashes already pretty-print well, and a short custom `inspect` is enough for small objects. The hook pays off for objects that wrap long collections - a parsed timetable, a configuration tree, an abstract syntax tree - that you dump often while debugging. Keep in mind that the ivar list `pp` shows by default is built separately from `Kernel#inspect`, so a class that filters `inspect` should check that `pp` honours the same filter.
- In Ruby, why does pp ignore line breaking for a class that overrides inspect?The default `pretty_print` from the pp library checks whether `inspect` is still the one from `Kernel`. If the class defines its own, pp writes that string with `q.text` as a single unbreakable unit, because it has no idea where the structure could break. Defining `pretty_print` restores wrapping.
- How do you capture pp's output in a String instead of writing it to standard output?Call `obj.pretty_inspect`, which returns the pretty-printed text with a trailing newline, or `PP.pp(obj, +"", width)` to choose the width explicitly; `PP.pp` returns the output object it wrote to.
saying these in an interview costs you the question
- pp returns nil like puts, so it cannot wrap an expression.
- pp calls each object's to_s and indents the result.
- pp wraps a custom inspect string at the terminal width.
- Customising pp means overriding pretty_inspect to return a formatted string.