skip to content

When you rewrite a right-to-left photo pipeline as a left-to-right pipe, what must match between adjacent stages?

level: middleimportance: should knowfreq 48%

answer

  1. a chain is a series of joins
  2. output must fit the next input
  3. direction flips the reading, not the rule
  4. uniform shapes hide wrong orderings
  5. adapt at the join, no auto-conversion

basics

~10 s

Each stage's result must be something the stage that receives it next accepts. That join requirement is identical in both directions; only the direction you read it along the written listing changes.

solid answer

~40 s

A chain is a series of joins, and every join has the same requirement: whatever one stage returns has to be acceptable as the next stage's argument. If `resize` returns a photo, `watermark` must take a photo; if `compress` returns bytes, only something that takes bytes may follow it. In a left-to-right listing you check that requirement by reading along the line; in a right-to-left listing you check the same requirement reading backwards, from the stage nearest the argument. Nothing adapts automatically: a stage that returns the wrong shape has to be wrapped by a small adapter stage, or the chain has to be resliced so the shapes meet.

code

pseudocode · 9 lines
pseudocode
resize:    photo -> photo
watermark: photo -> photo
compress:  photo -> bytes

ok     = pipe(resize, watermark, compress)     // photo -> bytes
broken = pipe(resize, compress, watermark)     // watermark is handed bytes

// same chain, read right to left:
same   = compose(compress, watermark, resize)  // input on the right, output on the left

go deeper

for a junior

Recall the one rule: what a stage returns has to be what the next stage takes. Be able to point at a listing and say which two stages meet at a given join.

for a middle

Explain that direction only changes which way you read the joins, and that a right-to-left listing puts the chain's input on the right and its output on the left - the reverse of a signature.

for a senior

Show that uniformly shaped stages satisfy every join in every order, so shape checking catches nothing there, and say what you would assert instead about such a chain.

for a principal

Weigh deliberately distinct stage shapes, which make wrong orderings inexpressible, against the adapters they force at every join, and say where on that line your codebase should sit.

A composed chain is not a bag of functions - it is a sequence of **joins**, and each join carries one requirement: the value produced by one stage must be something the next stage can accept. Direction changes which way you read that requirement along the written line; it does not change the requirement. ## The join, stated once Take the upload chain with its shapes spelled out: - `resize`: photo to photo - `watermark`: photo to photo - `compress`: photo to **bytes** The chain has two joins: `resize` to `watermark` (photo meets photo) and `watermark` to `compress` (photo meets photo). The chain as a whole is therefore photo to bytes. Adding a fourth stage is only legal if it accepts bytes, because bytes is what the chain now produces. ## The same constraint, read two ways | | Left-to-right listing | Right-to-left listing | |---|---|---| | The listing | `pipe(resize, watermark, compress)` | `compose(compress, watermark, resize)` | | Where the argument enters | leftmost stage | rightmost stage | | Direction you verify joins | left to right, along the line | right to left, against the line | | Chain's overall shape | first stage's input to last stage's output | rightmost stage's input to leftmost stage's output | The practical consequence is small but real: in a right-to-left listing, the *ends* of the chain are the *outside* of the line. The chain's input type is on the far right and its output type is on the far left, which is the opposite of how a function signature is usually read. Reviewers who forget this check the wrong end of a long listing. ## Why a wrong order is not merely ugly Swap two stages and one join breaks. `pipe(resize, compress, watermark)` asks `watermark` to accept **bytes**, which it does not take - the chain is not just in a surprising order, it is incoherent. That is worth saying out loud in an interview, because it is the reason mismatched shapes are a useful safety net: the more the shapes differ along the chain, the fewer wrong orderings are even expressible. The flip side is the dangerous case. When every stage is photo to photo, **every** ordering satisfies every join, and nothing about the shapes tells you the intended order. Direction mistakes in uniformly shaped chains are invisible to any check that only looks at how the stages fit together. ## When a stage does not fit the join Three honest options, in rough order of preference: 1. **Adapt at the join.** Insert a small stage that turns what you have into what the next stage wants - for instance a stage that takes a pair of photo and audit line and passes only the photo onward. 2. **Reslice the stage.** If a stage returns a photo plus a log line only because it was convenient, split it: one stage that transforms, one that records, and route the record outside the chain. 3. **Change the stage's own shape.** If the same adapter appears at every use site, the stage is simply the wrong shape; fix it once rather than patching each chain. What is not an option is hoping the combinator will convert for you. A composition helper applies functions; it does not coerce, reorder, or skip a stage to make the shapes work out. ## Where a mismatch surfaces Languages differ in when the mismatch is reported, and the difference matters for how you debug. Where the chain's shapes are checked before it runs, the complaint arrives at the join - the wiring line itself is rejected, and the fix is obvious. Where they are not, the wiring line is accepted, the chain is built happily, and the failure happens later and elsewhere: inside the stage that was handed the wrong shape, at the moment the built function is finally applied to a photo. The trace points at `watermark`, but the defect is in the listing that put `compress` in front of it. Knowing which situation you are in tells you whether to read the error or read the wiring. ## What an interviewer is listening for The expected answer names the join - **result of one stage matches the parameter of the next** - and then notes that direction only flips the reading, not the rule. The stronger answer goes one step further: chains whose stages all share one shape are the ones where nothing catches a wrong order, so their correctness has to be asserted some other way.

  • A stage returns a photo plus an audit line, but the next stage takes only a photo - what do you do?
    Adapt at the join: insert a stage that takes the pair and passes the photo onward, so the chain's shapes line up again. If the pairing exists only for convenience, reslice instead - one stage transforms, another records, and the audit line leaves the chain rather than travelling through every later join as dead weight.
  • Which orderings of a three-stage chain are ruled out by the shapes alone?
    Only those that break a join. With photo-to-photo, photo-to-photo and photo-to-bytes stages, anything that places the bytes-producing stage before another photo-taking stage is ruled out, which leaves two orderings of the first two stages. Shapes constrain the ordering; they rarely determine it.
  • Does adding a fourth stage to the end change the joins you already checked?
    No. Existing joins keep their two stages and their requirement; the new stage adds exactly one join, between the previous last stage's result and the new stage's parameter. What does change is the chain's overall output shape, which every caller of the chain now sees.

saying these in an interview costs you the question

  • Believes adjacent stages only need matching names
  • Thinks the helper converts a mismatched result automatically
  • Says the join reads left to right in a right-to-left listing
  • Assumes any stage can be dropped anywhere in the chain
  • Assumes every mismatch is reported before the chain runs