You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
V version: V 0.5.1 99f141f74 (verified no relevant commits land between that and current master b6dfae560)
OS-agnostic
Context
Issue #36 (closed 2021-01-05 as COMPLETED) covered the broader iterator/generator question. V today satisfies "iterator" via the next() ?T interface pattern, which is fine for stateless or simple stateful iteration. It does not satisfy "generator" in the Python / Rust gen / C# yield return / Kotlin sequence { yield(…) } sense: a function whose body suspends at yield points and resumes on the next consumer pull.
This issue is a focused request for yield-style generators, not for re-litigating next()-iterators.
Use case
Streaming row iteration over a multi-GB table. The natural shape:
fn iter_rows(t Table) Iter[Row] {
for chunk in t.chunks() {
for row in chunk.rows {
yield row // <-- requested syntax
}
}
}
Today the only way to express this is to either:
Materialise the entire result eagerly into []Row and return it — defeats streaming, blows memory on large tables.
Hand-write a struct ChunkRowIter { mut: chunk_idx int; row_idx int } with a next() ?Row that re-creates the nested loop state machine manually. Boilerplate scales with loop depth and nested conditions.
Proposed syntax
V-flavoured options to consider — the actual surface is up to V:
// Style A: yield keyword inside fn returning Iter[T]
fn rows() Iter[Row] {
for c in chunks { for r in c.rows { yield r } }
}
// Style B: gen block, modelled on Rust nightly
gen rows() Row {
for c in chunks { for r in c.rows { yield c.rows[r] } }
}
Downstream evidence
CX's lang/v/cffi/table.v:181-191 documents this as the reason its iter_rows API returns []map[string]CellValue eagerly rather than streaming. The C ABI underneath is fully chunked, but the V binding has to materialise because V can't express the lazy iterator.
Why not channels / goroutines?
V's chan + spawn can simulate generators, but every yield-point becomes a thread-safe channel send/receive and the consumer-side for loop becomes a for r in ch {}. The cost is real: extra OS thread, extra synchronisation. Generators are a single-stack abstraction; channels are a multi-stack one. Different tool.
Note
You can use the 👍 reaction to increase the issue's priority for developers.
Please note that only the 👍 reaction to the issue itself counts as a vote.
Other reactions and those to comments will not be taken into account.
This discussion was converted from issue #27173 on May 24, 2026 20:28.
Heading
Bold
Italic
Quote
Code
Link
Numbered list
Unordered list
Task list
Attach files
Mention
Reference
Menu
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Environment
V 0.5.1 99f141f74(verified no relevant commits land between that and current masterb6dfae560)Context
Issue #36 (closed 2021-01-05 as COMPLETED) covered the broader iterator/generator question. V today satisfies "iterator" via the
next() ?Tinterface pattern, which is fine for stateless or simple stateful iteration. It does not satisfy "generator" in the Python / Rustgen/ C#yield return/ Kotlinsequence { yield(…) }sense: a function whose body suspends atyieldpoints and resumes on the next consumer pull.This issue is a focused request for yield-style generators, not for re-litigating
next()-iterators.Use case
Streaming row iteration over a multi-GB table. The natural shape:
Today the only way to express this is to either:
[]Rowand return it — defeats streaming, blows memory on large tables.struct ChunkRowIter { mut: chunk_idx int; row_idx int }with anext() ?Rowthat re-creates the nested loop state machine manually. Boilerplate scales with loop depth and nested conditions.Proposed syntax
V-flavoured options to consider — the actual surface is up to V:
Downstream evidence
CX's
lang/v/cffi/table.v:181-191documents this as the reason itsiter_rowsAPI returns[]map[string]CellValueeagerly rather than streaming. The C ABI underneath is fully chunked, but the V binding has to materialise because V can't express the lazy iterator.Why not channels / goroutines?
V's
chan+spawncan simulate generators, but every yield-point becomes a thread-safe channel send/receive and the consumer-sideforloop becomes afor r in ch {}. The cost is real: extra OS thread, extra synchronisation. Generators are a single-stack abstraction; channels are a multi-stack one. Different tool.Note
You can use the 👍 reaction to increase the issue's priority for developers.
Please note that only the 👍 reaction to the issue itself counts as a vote.
Other reactions and those to comments will not be taken into account.
Beta Was this translation helpful? Give feedback.
All reactions