Skip to content

Instantly share code, notes, and snippets.

@carld
Forked from sharplet/lazy_reduce.rb
Created April 12, 2023 01:08
Show Gist options
  • Save carld/0145c0d75caefef3741ce2f869ccac3a to your computer and use it in GitHub Desktop.
Save carld/0145c0d75caefef3741ce2f869ccac3a to your computer and use it in GitHub Desktop.
Lazy `#reduce` and `#join` in Ruby
require "rspec/autorun"
class Enumerator::Lazy
def reduce(*)
Lazy.new([nil]) do |yielder, _|
yielder << super
end
end
def join(separator="")
reduce do |str, each|
"%s%s%s" % [str, separator, each]
end
end
end
RSpec.describe Enumerator::Lazy do
shared_examples_for "a lazy method" do
it "doesn't call its block" do
called = false
method.call do
called = true
end
expect(called).to be_falsy
end
end
subject { [1, 2, 3].lazy }
describe "#reduce" do
it_behaves_like "a lazy method" do
let(:method) { subject.public_method(:reduce) }
end
it "accepts the same number of arguments as Enumerable#reduce" do
enumerable = Object.new.extend(Enumerable).public_method(:reduce)
lazy = subject.public_method(:reduce)
expect(lazy.arity).to eq(enumerable.arity)
end
it "yields the result of calling reduce when forced" do
eager_sum = [1, 2, 3].reduce(0, :+)
lazy_sum = subject.reduce(0, :+)
expect(lazy_sum.first).to eq(eager_sum)
end
end
describe "#join" do
it_behaves_like "a lazy method" do
let(:method) { subject.public_method(:join) }
end
it "stringifies and joins values" do
expect(subject.join(",").first).to eq("1,2,3")
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment