Last active
February 27, 2020 02:39
-
-
Save JoshCheek/20f1bd6d82b4de4423be6bfb6bf4a8a5 to your computer and use it in GitHub Desktop.
Using refinements to monkey patch a reversed `reduce` in Ruby
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Consistency | |
original = Enumerable.instance_method :reduce | |
refine Enumerable do | |
# I didn't actually check it against the real impl or docs or anything, but its something like this | |
alias_method :inject, define_method(:reduce) { |*args, &block| | |
block = args.pop if args.size == 2 | |
Enumerator.new do |y| | |
original.bind(self).call(*args) { |l, r| y.yield r, l } | |
end.each &block | |
} | |
end | |
end | |
class A | |
# # it is reversed | |
%w[a b c].reduce &:+ # => "abc" | |
using Consistency | |
%w[a b c].reduce &:+ # => "cba" | |
# initial value + a symbol | |
%w[a b c].reduce "-abc", :+ # => "cba-abc" | |
# initial value + a block | |
%w[a b c].reduce "-abc", &:+ # => "cba-abc" | |
# initial value + a symbol + a block (prefers symbol over block) | |
%w[a b c].reduce("-abc", :+) { |l, r| r + l } # => "cba-abc" | |
# chainable | |
%w[a b c].reduce("!").with_index do |(char, str), index| | |
"#{str} #{index}:#{char}" | |
end # => "! 0:a 1:b 2:c" | |
# wrong number of args | |
%w[a b c].reduce("", :+, 123) # => #<Enumerator: #<Enumerator::Generator:0x00007fbffc983d20>:each> | |
end | |
# no effect outside the lexical scope, we're back to normal | |
%w[a b c].reduce &:+ # => "abc" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment