Skip to content

Instantly share code, notes, and snippets.

@noprompt
Last active February 18, 2016 21:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save noprompt/90ec4999245b3bf6c009 to your computer and use it in GitHub Desktop.
Save noprompt/90ec4999245b3bf6c009 to your computer and use it in GitHub Desktop.
Port of clojure.walk to Ruby
module Walk
refine Array do
def walk(inner_f, outer_f)
outer_f.(self.map(&inner_f))
end
end
refine Hash do
def walk(inner_f, outer_f)
outer_f.(self.map { |e| e.map(&inner_f) }.to_h)
end
end
refine Object do
def walk(_inner_f, outer_f)
outer_f.(self)
end
end
using self
def self.walk(inner_f, outer_f, object)
object.walk(inner_f, outer_f)
end
def self._postwalk(f, object)
g = self.method(:_postwalk).curry.(f)
walk(g, f, object)
end
def self.postwalk(object, &block)
_postwalk(block, object)
end
def self._prewalk(f, object)
g = self.method(:_prewalk).curry.(f)
walk(g, :itself.to_proc, f.(object))
end
def self.prewalk(object, &block)
_prewalk(block, object)
end
end
@noprompt
Copy link
Author

data = {
  foo: {
    foo: [
      { foo: "bar" },
      { foo: "baz" }
    ]
  }
}


Walk.prewalk(data) {|x| puts x.inspect ; x }
# {:foo=>{:foo=>[{:foo=>"bar"}, {:foo=>"baz"}]}}
# :foo
# {:foo=>[{:foo=>"bar"}, {:foo=>"baz"}]}
# :foo
# [{:foo=>"bar"}, {:foo=>"baz"}]
# {:foo=>"bar"}
# :foo
# "bar"
# {:foo=>"baz"}
# :foo
# "baz"
# => {:foo=>{:foo=>[{:foo=>"bar"}, {:foo=>"baz"}]}}


Walk.postwalk(data) {|x| puts x.inspect ; x }
# :foo
# :foo
# :foo
# "bar"
# {:foo=>"bar"}
# :foo
# "baz"
# {:foo=>"baz"}
# [{:foo=>"bar"}, {:foo=>"baz"}]
# {:foo=>[{:foo=>"bar"}, {:foo=>"baz"}]}
# {:foo=>{:foo=>[{:foo=>"bar"}, {:foo=>"baz"}]}}
# => {:foo=>{:foo=>[{:foo=>"bar"}, {:foo=>"baz"}]}}

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