Skip to content

Initialize default traversal state when component enumerators run - #36

Open
OskarEichler wants to merge 1 commit into
ruby:masterfrom
OskarEichler:codex/restart-tsort-enumerators
Open

Initialize default traversal state when component enumerators run#36
OskarEichler wants to merge 1 commit into
ruby:masterfrom
OskarEichler:codex/restart-tsort-enumerators

Conversation

@OskarEichler

Copy link
Copy Markdown

Summary

Create default traversal state when a component-from-node enumerator runs, so it can be enumerated again or rewound. Preserve explicitly supplied state objects for callers that intentionally share traversal state.

Reproduction

graph = {1 => [2], 2 => [3], 3 => []}
children = ->(node, &block) { graph.fetch(node).each(&block) }
enum = TSort.each_strongly_connected_component_from(1, children)
p enum.to_a # [[3], [2], [1]]
p enum.to_a # currently [[1]]
enum.rewind
p enum.to_a # currently [[1]]

The default hash and stack are currently created before to_enum and captured in its arguments. Later enumerations reuse visited-node state. Deferring allocation until the block path makes implicit state fresh on each run. The mixin entry point gets the same correction.

Verification

Ruby 4.0.6 through rbenv:

  • Existing suite: 8 tests / 17 assertions, no failures.
  • 15 external checks pass for class/mixin entry points, repeated to_a, next then rewind, take then complete enumeration, and explicit shared state.
  • Combined with the separate direct-block-forwarding patch on a 0.2.0 release-based branch: the same suite, these checks, and 4,000 graph checks pass; graph results match the baseline.
  • Ruby syntax, gem build and git diff --check pass. No dependency or version changes.

No tests were added/modified under the requesting project's policy; repros are external. Local verification covers macOS/Ruby 4.0.6, not the full upstream matrix. Explicitly supplied state remains caller-owned and can intentionally affect subsequent enumerations.

Breaking-change notes

Repeated enumeration with implicit state now repeats the complete traversal instead of silently omitting previously visited children. Explicit state behavior is preserved. Passing nil for either optional state argument now selects a fresh default instead of failing incidentally. Cycle/self-loop semantics and traversal ordering are unchanged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant