Skip to content

Instantly share code, notes, and snippets.

@techwhizbang
Created July 21, 2011 06:38
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save techwhizbang/1096650 to your computer and use it in GitHub Desktop.
Save techwhizbang/1096650 to your computer and use it in GitHub Desktop.
Ruby inject method implementation
require 'rubygems'
require 'rspec'
module Enumerable
def inject(*args, &block)
if(args.size == 2)
inject_binary_operation(args[0], args[1], self)
elsif(args.size == 1 && !block_given?)
inject_binary_operation(self.first, args[0], self.drop(1))
else
the_memo = args[0] || self.first
self.each { |item| the_memo = yield(the_memo, item) if block_given? }
the_memo
end
end
alias :reduce :inject
private
def inject_binary_operation(the_memo, operator, enum)
raise TypeError.new("#{operator} is not a symbol") unless operator.is_a?(Symbol)
enum.each { |item| the_memo = the_memo.send(operator, item) }
the_memo
end
end
shared_examples_for "an Enumerable object" do
describe "inject" do
describe "given there is a specified memo value" do
it('should return the newly injected "memo" value if using a block') do
enumerable.inject([3,4,5]) { |memo, enum_item| memo.include?(enum_item) ? memo : memo << enum_item }.should == [3, 4, 5, 1, 2]
end
describe "when it is a binary operation" do
it('should return a TypeError because the single argument is not a Symbol') do
lambda { enumerable.inject(2) }.should raise_error(TypeError)
end
it('should add the values') do
enumerable.inject(2, :+).should == 8
end
it('should multiply the values') do
enumerable.inject(2, :*).should == 12
end
it('should subtract the values') do
enumerable.inject(2, :-).should == -4
end
end
end
describe "given there isn't a specified memo value" do
it('should return the newly injected "memo" value if using a block') do
enumerable.inject { |memo, enum_item| memo > enum_item ? memo : enum_item }.should == 3
end
describe "when it is a binary operation" do
it('should add the values') do
enumerable.inject(:+).should == 6
end
it('should multiply the values') do
enumerable.inject(:*).should == 6
end
it('should subtract the values') do
enumerable.inject(:-).should == -4
end
end
end
end
end
describe Range do
it_should_behave_like "an Enumerable object" do
let(:enumerable) { (1..3) }
end
end
describe Array do
it_should_behave_like "an Enumerable object" do
let(:enumerable) { [1,2,3] }
end
end
@mosesmuchemi
Copy link

thanks man this is beautiful

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