Number the checklist
Requirement
Turn six setup steps into a numbered checklist — 1. Unbox
the sensor kit and so on, one line per step, numbering from
one. The data is in the code; both versions must print the lines
shown under Expected output.
Expected output
1. Unbox the sensor kit 2. Charge the base station 3. Pair the remote 4. Mount the wall bracket 5. Run the self-test 6. Register the warranty
Side by side
RxDart
FxDart
Why they differ
Neither core Stream nor RxDart has an indexed
map. The closest thing RxDart offers is
scan, whose accumulator happens to receive an index as
its third argument — so the rx spelling shown numbers the steps by
riding a fold: a seed you must invent ('') and
an accumulated value you immediately ignore. The alternatives are no
cleaner in kind — a mutable counter the mapper closes over, or
zipping against Rx.range — every route smuggles the
index in from outside, because no operator carries it. It works, and
it still reads like a workaround.
FxDart says the thing directly: zipWithIndex pairs each
element with its position, and a plain map formats the
pair. This is not a push-vs-pull gap so much as a vocabulary gap —
an indexed pairing operator is trivially expressible in either model,
Rx just never grew one — but the reader of each panel feels it: one
side states "element with its index", the other encodes it in an
accumulator's spare parameter. Verdict: FxDart.
Benchmark
N = 100
Time Tie
Peak memory Tie
N = 1,000,000
Time FxDart wins
Peak memory Tie
Bars are medians of repeated timed iterations in fresh processes per side (small N is batched for timer resolution). Sides within 5% of each other — or within 0.6 ms, a difference no person can perceive — count as a tie; close relative races are re-measured up to 5 runs. In an app, anything under a few milliseconds is invisible to the user regardless of which bar is shorter. Memory is peak process RSS. The Dart VM and the dataset are identical on both sides, so the difference between the two bars is what the pipeline itself holds onto.