Saturday, August 17, 2013

Weird closure behavior in Ruby

Weird closure behavior in Ruby

I was messing around with closures in Ruby and came across the following
scenario that I can not understand.
def find_child_nodes(node)
left_node_name = "#{node}A"
right_node_name = "#{node}B"
[left_node_name, right_node_name]
end
# use a stack of closures (lambdas) to try to perform a breadth-first search
actions = []
actions << lambda { {:parent_nodes => ['A'], :child_nodes =>
find_child_nodes('A') } }
while !actions.empty?
result = actions.shift.call
puts result[:parent_nodes].to_s
result[:child_nodes].each do |child_node|
parent_nodes = result[:parent_nodes] + [child_node]
actions << lambda { {:parent_nodes => parent_nodes, :child_nodes =>
find_child_nodes(child_node) } }
end
end
The above code returns the following breadth-first search output:
["A"]
["A", "AA"]
["A", "AB"]
["A", "AA", "AAA"]
["A", "AA", "AAB"]
["A", "AB", "ABA"]
["A", "AB", "ABB"]
["A", "AA", "AAA", "AAAA"]
...
So far, so good. But now if I change these two lines
parent_nodes = result[:parent_nodes] + [child_node]
actions << lambda { {:parent_nodes => parent_nodes, :child_nodes =>
find_child_nodes(child_node) } }
to this one line
actions << lambda { {:parent_nodes => result[:parent_nodes] +
[child_node], :child_nodes => find_child_nodes(child_node) } }
My search is no longer breadth-first. Instead I now get
["A"]
["A", "AA"]
["A", "AA", "AB"]
["A", "AA", "AB", "AAA"]
["A", "AA", "AB", "AAA", "AAB"]
...
Could anyone explain exactly what's going on here?

No comments:

Post a Comment