Last active
November 13, 2019 18:28
-
-
Save havenwood/85734cd9a9db1cbbdfbb845467544e49 to your computer and use it in GitHub Desktop.
Playing with Enumerator.produce from Ruby 2.7
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
class Node | |
attr_reader :value | |
attr_reader :parent | |
def initialize(value:, parent: nil) | |
@value = value | |
@parent = parent | |
end | |
def ancestors | |
return [] unless @parent | |
Enumerator.produce @parent do |child| | |
child.parent || raise(StopIteration) | |
end.to_a | |
end | |
end | |
require 'minitest/autorun' | |
describe Node do | |
let(:parent) { Node.new value: 42 } | |
let(:child) { Node.new parent: parent, value: 22 } | |
let(:grandchild) { Node.new parent: child, value: 2 } | |
describe 'values' do | |
it 'has a value' do | |
assert_equal 42, parent.value | |
assert_equal 22, child.value | |
assert_equal 2, grandchild.value | |
end | |
end | |
describe 'parents' do | |
describe 'a very long chain' do | |
it 'does not blow up' do | |
high_number = 20_000 | |
variables = ('a'..).take(high_number) | |
variables.each_cons(2) do |a, b| | |
instance_variable_set "@#{b}", Node.new(value: b, parent: instance_variable_get("@#{a}")) | |
end | |
assert_equal high_number - 2, instance_variable_get("@#{variables.last}").ancestors.size | |
end | |
end | |
describe 'the first generation' do | |
it 'has no parent' do | |
assert_nil parent.parent | |
end | |
it 'has no ancestry' do | |
assert_empty parent.ancestors | |
end | |
end | |
describe 'a grandchild' do | |
it 'has a parent' do | |
assert_equal child, grandchild.parent | |
end | |
describe 'ancestors' do | |
it 'has two ancestors' do | |
assert_equal 2, grandchild.ancestors.size | |
end | |
it 'lists the child first' do | |
assert_equal child, grandchild.ancestors.first | |
end | |
it 'lists the parent last' do | |
assert_equal parent, grandchild.ancestors.last | |
end | |
end | |
end | |
end | |
end |
Only downside would be it blowing up with really long chains. For the same order:
parent.ancestors.prepend parent
Or using a while loop:
def ancestors
node = self
ancestors = []
ancestors << node while (node = node.parent)
ancestors
end
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I would use something like: