Guest User

Untitled

a guest
Feb 19th, 2018
108
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.08 KB | None | 0 0
  1. require 'enumerator'
  2.  
  3. # The future always arrives too fast... and in the wrong order.
  4. module Future; end # :nodoc:
  5.  
  6. # Makes most methods that usually take blocks do the same thing
  7. # as they will do in the future: Return an enumerator if no block
  8. # is supplied to them. This is neat:
  9. #
  10. # items = ["perl", "python", "ruby"]
  11. # result = items.each_with_index.find do |item, index|
  12. # not item.include?("p")
  13. # end
  14. # found_item, found_index = *result
  15. # found_item # => "ruby"
  16. # found_index # => 2
  17. #
  18. # "foobar".each_byte.map do |byte|
  19. # byte.succ.chr
  20. # end.join # => "gppcbs"
  21. #
  22. # str = (0 .. 15).each_with_index.map do |item, index|
  23. # ("%04b" % item).tr("01", " #") +
  24. # (index % 4 == 3 ? "\n" : "|")
  25. # end.join
  26. # puts str
  27. # # outputs:
  28. # # | #| # | ##
  29. # # # | # #| ## | ###
  30. # # # |# #|# # |# ##
  31. # # ## |## #|### |####
  32. module Future::Enumerator
  33. extend self
  34.  
  35. OldMethods = {} unless defined?(OldMethods) # :nodoc:
  36.  
  37. def enumeratify(mod, method)
  38. method = method.to_sym
  39. key = [mod, method].join("#")
  40. # We're still in 1.8. Blocks can't take blocks.
  41. # So we need to use the string form of module_eval.
  42. # It's sad and allows for code injection bugs. :(
  43. return false if OldMethods.include?(key)
  44. old_method = mod.instance_method(method)
  45. mod.module_eval { remove_method(method) }
  46. mod.module_eval(%(
  47. def #{method}(*args, &block)
  48. if block then
  49. old = Future::Enumerator::OldMethods[#{key.inspect}]
  50. old.bind(self).call(*args, &block)
  51. else
  52. enum_for(#{method.inspect}, *args)
  53. end
  54. end
  55. ), File.join(__FILE__, key), 0)
  56. OldMethods[key] = old_method
  57. return true
  58. end
  59. private :enumeratify
  60.  
  61. def meta(mod)
  62. class << mod; self; end
  63. end
  64. private :meta
  65.  
  66.  
  67. # A list of all modules/classes and their methods which will
  68. # return an Enumerator if no block is given. This is hard to
  69. # read in the RDoc and I can't do much about it, unfortunately.
  70. EnumeratifyRules = {
  71. meta(ARGF) => [:each, :each_byte, :each_line],
  72.  
  73. Array => [:collect, :collect!, :delete_if, :each, :each_index,
  74. :map, :map!, :reject, :reject!, :reverse_each, :select],
  75.  
  76. meta(Dir) => [:foreach],
  77. Dir => [:each],
  78.  
  79. Enumerable => [:collect, :detect, :each_with_index, :find,
  80. :find_all, :map, :partition, :reject, :select, :sort_by],
  81.  
  82. meta(ENV) => [:delete_if, :each, :each_key, :each_pair,
  83. :each_value, :reject, :reject!, :select],
  84.  
  85. Hash => [:each, :each_key, :each_pair, :each_value, :reject,
  86. :reject!, :select],
  87.  
  88. meta(IO) => [:foreach],
  89. IO => [:each, :each_byte, :each_line],
  90.  
  91. # Not in Ruby 1.9 (yet?)
  92. #Integer => [:downto, :upto],
  93. #Numeric => [:step],
  94.  
  95. Range => [:each, :step],
  96.  
  97. String => [:each, :each_byte, :each_line],
  98.  
  99. Struct => [:each, :each_pair],
  100. }
  101.  
  102.  
  103. if RUBY_VERSION < "1.9" then
  104. EnumeratifyRules.each do |mod, methods|
  105. methods.each do |method|
  106. enumeratify(mod, method)
  107. end
  108. end
  109. end
  110. end
Add Comment
Please, Sign In to add comment