lib/core/facets/hash/recursively.rb in facets-2.8.4 vs lib/core/facets/hash/recursively.rb in facets-2.9.0.pre.1

- old
+ new

@@ -1,29 +1,61 @@ +require 'facets/functor' +require 'facets/enumerable/recursively' + class Hash - # Apply a block to hash, and recursively apply that block - # to each subhash. + # Apply a block to a hash, and recursively apply that block + # to each sub-hash: # - # h = {:a=>1, :b=>{:b1=>1, :b2=>2}} - # h.recursively{|h| h.rekey(&:to_s) } - # => {"a"=>1, "b"=>{"b1"=>1, "b2"=>2}} + # h = {:a=>1, :b=>{:x=>1, :y=>2}} + # h.recursively.map{ |k,v| [k.to_s, v] } + # #=> [["a", 1], ["b", [["y", 2], ["x", 1]]]] # - def recursively(&block) - warn "Use #recusive instead of #recursively for future versions" - h = inject({}) do |hash, (key, value)| - if value.is_a?(Hash) - hash[key] = value.recursively(&block) - else - hash[key] = value + # The recursive iteration can be treated separately from the non-recursive + # iteration by passing a block to the #recursive method: + # + # h = {:a=>1, :b=>{:x=>1, :y=>2}} + # h.recursively{ |k,v| [k.to_s, v] }.map{ |k,v| [k.to_s, v.to_s] } + # #=> [["a", "1"], ["b", [["y", "2"], ["x", "1"]]]] + # + def recursively(*types, &block) + Recursor.new(self, *types, &block) + end + + class Recursor < Enumerable::Recursor #:nodoc: + def method_missing(op, &yld) + yld = yld || lambda{ |k,v| [k,v] } # ? to_enum + rec = @block || yld #lambda{ |k,v| [k,v] } + @enum.__send__(op) do |k,v| + case v + when String # b/c of 1.8 + yld.call(k,v) + when *@types + res = v.recursively(*@types, &@block).__send__(op,&yld) + rec.call(k, res) + else + yld.call(k,v) + end end - hash end - yield h end - # In place form of #recursively. - - def recursively!(&block) - replace(recursively(&block)) +## TODO: When no longer need 1.8.6 support. +=begin + def recursively(*types, &block) + types = types.empty? ? [self.class] : types + Functor.new do |op, &yld| + rec = block || yld + __send__(op) do |k,v| + case v + when *types + rec.call(k, v.recursively(*types, &block).__send__(op,&yld)) + else + yld.call(k,v) + end + end + end end +=end end +