A collection pipeline
Given `animals = %w(Jaguar Turtle Lion Antelope)`, `animals.select { |n| n[0] < 'M' }.map(&:upcase).join(', ')` produces `"JAGUAR, LION, ANTELOPE"`. Each call works on the preceding call’s result: select names, uppercase them, then join them. section 10.11
A chain makes a sequence of transformations read from left to right. In `"joe".upcase.reverse`, `"joe"` receives `upcase`; its result, `"JOE"`, receives `reverse`. The intermediate value is not printed or assigned. Chaining works smoothly here because both calls return strings and neither has a side effect. section 16.3.2
Check what each link returns before extending a chain:
- Collection chains can allocate intermediate objects. The animal pipeline creates arrays from `select` and `map`, then a string from `join`. Enumerators can reduce intermediate-object creation in some cases, but do not eliminate every cost. section 10.11
- Many iterators, including `each`, `map`, and `select`, return an enumerator when called without a block. That enumerator can receive the next method call. section 10.9.3
- A mutating method may interrupt the chain: `gsub!` returns `nil` when it makes no substitution, so a following string method would be called on `nil`. Use a nonmutating alternative such as `gsub`, or separate the calls when that return value matters. section 13.2.1
For a block-shaped step, `then` (also called `yield_self`) passes the receiver into the block and returns the block’s result, ready for another call. `tap` also passes in the receiver but returns that receiver instead. Choose between them according to which value the next link needs. `itself` simply returns its receiver; for example, `group_by(&:itself)` groups equal values by those values. section 16.3.3


