Skip to content

Instantly share code, notes, and snippets.

@brianm
Created May 18, 2011 21:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save brianm/979653 to your computer and use it in GitHub Desktop.
Save brianm/979653 to your computer and use it in GitHub Desktop.
require 'prettyprint' # for the p function
module Enumerable
alias :fold :inject
end
root = [["root", [
["child", [
["grandkid", []],
["grandkid2", []]]],
["child2", []]]]]
thunk = lambda do |a, (name, children)|
a << name.reverse
children.fold(a, &thunk)
end
p root.fold([], &thunk)
require 'prettyprint'
# This form of the FP style creates a definition for fold()
# for trees of the form [<value>, [<children>]]
module FoldableTree
# define fold for trees of the form [<value>, [<children>]]
# recursively applies the FoldableTree type to each node
def fold accumulator, &f
# note the use of structural decomposition,
# as (value, children) for elements in the tree
inject(accumulator) do |accumulator, (value, children)|
a2 = f.call accumulator, value
children.extend FoldableTree
children.fold a2, &f
end
end
end
root = [["root", [
["child", [
["grandkid", []],
["grandkid2", []]]],
["child2", []]]]]
# Declare our tree to be an instance of FoldableTree
root.extend FoldableTree
# Fold across our foldable tree, collecting names in reverse
p root.fold([]) do |a, name|
# create a new array each time, rather than mutate a
[a, name.reverse].flatten
end
require 'prettyprint' # for the p function
class Tree
attr_accessor :name
def initialize name
@name = name
@children = []
end
def visit visitor
visitor.visit(self)
for child in @children
child.visit(visitor)
end
visitor.value
end
def << child
@children << child
self
end
end
root = Tree.new("root") << (Tree.new("child") << Tree.new("grandkid") << Tree.new("grandkid2")) << Tree.new("child2")
class Visitor
attr_accessor :value
def initialize
@value = []
end
def visit node
@value << node.name.reverse
end
end
p root.visit(Visitor.new)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment