After #4838 stepped for ranges with |step| > 1 still compile to an enumerator loop
for i in a .. ±1 .. b now lowers to a counted loop (same as to/downto).
But an explicit step other than ±1 still allocates a range sequence + enumerator:
for i in 0 .. 2 .. n do f i
const enumerator = getEnumerator(rangeDouble(0, 2, n));
try { while (enumerator["...MoveNext"]()) { const i = enumerator["...get_Current"]() | 0; f(i); } }
finally { disposeSafe(enumerator); }
Why it's not done yet: Fable.ForLoop only encodes ±1 (i++/i--). A general constant step needs either a capture-safe while lowering (non-breaking, some care for #4031) or a step field on ForLoop (breaks Fable.AST → major version).
Note a runtime step can't be a counted loop at all (direction unknown at compile time).
Non +/- 1 constant steps are rare and the runtime win is small.
After #4838 stepped
forranges with|step| > 1still compile to an enumerator loopfor i in a .. ±1 .. bnow lowers to a counted loop (same asto/downto).But an explicit step other than ±1 still allocates a range sequence + enumerator:
Why it's not done yet: Fable.ForLoop only encodes ±1 (i++/i--). A general constant step needs either a capture-safe while lowering (non-breaking, some care for #4031) or a step field on ForLoop (breaks Fable.AST → major version).
Note a runtime step can't be a counted loop at all (direction unknown at compile time).
Non +/- 1 constant steps are rare and the runtime win is small.