Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- require 'enumerator'
- # The future always arrives too fast... and in the wrong order.
- module Future; end # :nodoc:
- # Makes most methods that usually take blocks do the same thing
- # as they will do in the future: Return an enumerator if no block
- # is supplied to them. This is neat:
- #
- # items = ["perl", "python", "ruby"]
- # result = items.each_with_index.find do |item, index|
- # not item.include?("p")
- # end
- # found_item, found_index = *result
- # found_item # => "ruby"
- # found_index # => 2
- #
- # "foobar".each_byte.map do |byte|
- # byte.succ.chr
- # end.join # => "gppcbs"
- #
- # str = (0 .. 15).each_with_index.map do |item, index|
- # ("%04b" % item).tr("01", " #") +
- # (index % 4 == 3 ? "\n" : "|")
- # end.join
- # puts str
- # # outputs:
- # # | #| # | ##
- # # # | # #| ## | ###
- # # # |# #|# # |# ##
- # # ## |## #|### |####
- module Future::Enumerator
- extend self
- OldMethods = {} unless defined?(OldMethods) # :nodoc:
- def enumeratify(mod, method)
- method = method.to_sym
- key = [mod, method].join("#")
- # We're still in 1.8. Blocks can't take blocks.
- # So we need to use the string form of module_eval.
- # It's sad and allows for code injection bugs. :(
- return false if OldMethods.include?(key)
- old_method = mod.instance_method(method)
- mod.module_eval { remove_method(method) }
- mod.module_eval(%(
- def #{method}(*args, &block)
- if block then
- old = Future::Enumerator::OldMethods[#{key.inspect}]
- old.bind(self).call(*args, &block)
- else
- enum_for(#{method.inspect}, *args)
- end
- end
- ), File.join(__FILE__, key), 0)
- OldMethods[key] = old_method
- return true
- end
- private :enumeratify
- def meta(mod)
- class << mod; self; end
- end
- private :meta
- # A list of all modules/classes and their methods which will
- # return an Enumerator if no block is given. This is hard to
- # read in the RDoc and I can't do much about it, unfortunately.
- EnumeratifyRules = {
- meta(ARGF) => [:each, :each_byte, :each_line],
- Array => [:collect, :collect!, :delete_if, :each, :each_index,
- :map, :map!, :reject, :reject!, :reverse_each, :select],
- meta(Dir) => [:foreach],
- Dir => [:each],
- Enumerable => [:collect, :detect, :each_with_index, :find,
- :find_all, :map, :partition, :reject, :select, :sort_by],
- meta(ENV) => [:delete_if, :each, :each_key, :each_pair,
- :each_value, :reject, :reject!, :select],
- Hash => [:each, :each_key, :each_pair, :each_value, :reject,
- :reject!, :select],
- meta(IO) => [:foreach],
- IO => [:each, :each_byte, :each_line],
- # Not in Ruby 1.9 (yet?)
- #Integer => [:downto, :upto],
- #Numeric => [:step],
- Range => [:each, :step],
- String => [:each, :each_byte, :each_line],
- Struct => [:each, :each_pair],
- }
- if RUBY_VERSION < "1.9" then
- EnumeratifyRules.each do |mod, methods|
- methods.each do |method|
- enumeratify(mod, method)
- end
- end
- end
- end
Add Comment
Please, Sign In to add comment