diff --git a/io.c b/io.c index 590e8d11d7..ca5e27c41f 100644 --- a/io.c +++ b/io.c @@ -4472,15 +4472,24 @@ rb_io_readlines(int argc, VALUE *argv, VALUE io) static VALUE io_readlines(const struct getline_arg *arg, VALUE io) { - VALUE line, ary; + VALUE line; if (arg->limit == 0) rb_raise(rb_eArgError, "invalid limit: 0 for readlines"); - ary = rb_ary_new(); - while (!NIL_P(line = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, io))) { - rb_ary_push(ary, line); + + // If a block is provided, yield lines. + if (rb_block_given_p()) { + while (!NIL_P(line = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, io))) { + rb_yield(line); + } + return Qnil; + } else { + VALUE ary = rb_ary_new(); + while (!NIL_P(line = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, io))) { + rb_ary_push(ary, line); + } + return ary; } - return ary; } /* diff --git a/spec/ruby/core/io/readlines_spec.rb b/spec/ruby/core/io/readlines_spec.rb index 3a6ff3d0f3..2cf930746c 100644 --- a/spec/ruby/core/io/readlines_spec.rb +++ b/spec/ruby/core/io/readlines_spec.rb @@ -20,6 +20,16 @@ describe "IO#readlines" do -> { @io.readlines }.should raise_error(IOError) end + ruby_version_is "3.3" do + describe "when invoked with a block" do + it "yields each line to the block" do + lines = [] + @io.readlines { |line| lines << line } + lines.should == IOSpecs.lines + end + end + end + describe "when passed no arguments" do before :each do suppress_warning {@sep, $/ = $/, " "} @@ -214,6 +224,14 @@ describe "IO.readlines" do IO.readlines(cmd) }.should complain(/IO process creation with a leading '\|'/) end + + describe "when invoked with a block" do + it "yields each line to the block" do + lines = [] + IO.readlines(@name) { |line| lines << line } + lines.should == IOSpecs.lines + end + end end it_behaves_like :io_readlines, :readlines